diff options
Diffstat (limited to 'test/libsolidity')
-rw-r--r-- | test/libsolidity/Assembly.cpp | 4 | ||||
-rw-r--r-- | test/libsolidity/JSONCompiler.cpp | 26 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 55 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 204 | ||||
-rw-r--r-- | test/libsolidity/StandardCompiler.cpp | 30 |
5 files changed, 294 insertions, 25 deletions
diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index e52f4d50..99a2996e 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -119,8 +119,8 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr<string const> n = make_shared<string>(""); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(17, SourceLocation(2, 75, n)) + - vector<SourceLocation>(30, SourceLocation(20, 72, n)) + + vector<SourceLocation>(19, SourceLocation(2, 75, n)) + + vector<SourceLocation>(32, SourceLocation(20, 72, n)) + vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector<SourceLocation>(2, SourceLocation(58, 67, n)) + vector<SourceLocation>(3, SourceLocation(20, 72, n)); diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp index f5154395..aa690f0b 100644 --- a/test/libsolidity/JSONCompiler.cpp +++ b/test/libsolidity/JSONCompiler.cpp @@ -73,28 +73,36 @@ BOOST_AUTO_TEST_CASE(basic_compilation) Json::Value contract = result["contracts"]["fileA:A"]; BOOST_CHECK(contract.isObject()); BOOST_CHECK(contract["interface"].isString()); - BOOST_CHECK(contract["interface"].asString() == "[]"); + BOOST_CHECK_EQUAL(contract["interface"].asString(), "[]"); BOOST_CHECK(contract["bytecode"].isString()); - BOOST_CHECK(dev::test::bytecodeSansMetadata(contract["bytecode"].asString()) == - "60606040523415600b57fe5b5b60338060196000396000f30060606040525bfe00"); + BOOST_CHECK_EQUAL( + dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), + "60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00" + ); BOOST_CHECK(contract["runtimeBytecode"].isString()); - BOOST_CHECK(dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()) == - "60606040525bfe00"); + BOOST_CHECK_EQUAL( + dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()), + "60606040525b600080fd00" + ); BOOST_CHECK(contract["functionHashes"].isObject()); BOOST_CHECK(contract["gasEstimates"].isObject()); - BOOST_CHECK(dev::jsonCompactPrint(contract["gasEstimates"]) == - "{\"creation\":[62,10200],\"external\":{},\"internal\":{}}"); + BOOST_CHECK_EQUAL( + dev::jsonCompactPrint(contract["gasEstimates"]), + "{\"creation\":[62,10800],\"external\":{},\"internal\":{}}" + ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); BOOST_CHECK(result["sources"].isObject()); BOOST_CHECK(result["sources"]["fileA"].isObject()); BOOST_CHECK(result["sources"]["fileA"]["AST"].isObject()); - BOOST_CHECK(dev::jsonCompactPrint(result["sources"]["fileA"]["AST"]) == + BOOST_CHECK_EQUAL( + dev::jsonCompactPrint(result["sources"]["fileA"]["AST"]), "{\"attributes\":{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]}}," "\"children\":[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null]," "\"contractKind\":\"contract\",\"documentation\":null,\"fullyImplemented\":true,\"linearizedBaseContracts\":[1]," "\"name\":\"A\",\"nodes\":[null],\"scope\":2},\"id\":1,\"name\":\"ContractDefinition\"," - "\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}"); + "\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}" + ); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index ba507e0c..ffee5e36 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4483,6 +4483,38 @@ BOOST_AUTO_TEST_CASE(array_copy_including_mapping) BOOST_CHECK(storageEmpty(m_contractAddress)); } +BOOST_AUTO_TEST_CASE(swap_in_storage_overwrite) +{ + // This tests a swap in storage which does not work as one + // might expect because we do not have temporary storage. + // (x, y) = (y, x) is the same as + // y = x; + // x = y; + char const* sourceCode = R"( + contract c { + struct S { uint a; uint b; } + S public x; + S public y; + function set() { + x.a = 1; x.b = 2; + y.a = 3; y.b = 4; + } + function swap() { + (x, y) = (y, x); + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0), u256(0))); + BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(0), u256(0))); + BOOST_CHECK(callContractFunction("set()") == encodeArgs()); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1), u256(2))); + BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(3), u256(4))); + BOOST_CHECK(callContractFunction("swap()") == encodeArgs()); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1), u256(2))); + BOOST_CHECK(callContractFunction("y()") == encodeArgs(u256(1), u256(2))); +} + BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base) { char const* sourceCode = R"( @@ -9469,6 +9501,29 @@ BOOST_AUTO_TEST_CASE(revert) BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(42))); } +BOOST_AUTO_TEST_CASE(literal_empty_string) +{ + char const* sourceCode = R"( + contract C { + bytes32 public x; + uint public a; + function f(bytes32 _x, uint _a) { + x = _x; + a = _a; + } + function g() { + this.f("", 2); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs()); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(2))); +} + BOOST_AUTO_TEST_CASE(scientific_notation) { char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index a1428972..c8a04539 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -554,6 +554,51 @@ BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) CHECK_SUCCESS(text); } +BOOST_AUTO_TEST_CASE(comparison_of_function_types) +{ + char const* text = R"( + contract C { + function f() returns (bool ret) { + return this.f < this.f; + } + } + )"; + CHECK_ERROR(text, TypeError, "Operator < not compatible"); + text = R"( + contract C { + function f() returns (bool ret) { + return f < f; + } + } + )"; + CHECK_ERROR(text, TypeError, "Operator < not compatible"); + text = R"( + contract C { + function f() returns (bool ret) { + return f == f; + } + function g() returns (bool ret) { + return f != f; + } + } + )"; + CHECK_SUCCESS(text); +} + +BOOST_AUTO_TEST_CASE(comparison_of_mapping_types) +{ + char const* text = R"( + contract C { + mapping(uint => uint) x; + function f() returns (bool ret) { + var y = x; + return x == y; + } + } + )"; + CHECK_ERROR(text, TypeError, "Operator == not compatible"); +} + BOOST_AUTO_TEST_CASE(function_no_implementation) { ASTPointer<SourceUnit> sourceUnit; @@ -1049,6 +1094,28 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables) CHECK_SUCCESS(text); } +BOOST_AUTO_TEST_CASE(function_modifier_double_invocation) +{ + char const* text = R"( + contract B { + function f(uint x) mod(x) mod(2) { } + modifier mod(uint a) { if (a > 0) _; } + } + )"; + CHECK_ERROR(text, DeclarationError, "Modifier already used for this function"); +} + +BOOST_AUTO_TEST_CASE(base_constructor_double_invocation) +{ + char const* text = R"( + contract C { function C(uint a) {} } + contract B is C { + function B() C(2) C(2) {} + } + )"; + CHECK_ERROR(text, DeclarationError, "Base constructor already provided"); +} + BOOST_AUTO_TEST_CASE(legal_modifier_override) { char const* text = R"( @@ -2183,6 +2250,36 @@ BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1) ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Type resolving failed"); } +BOOST_AUTO_TEST_CASE(warns_assigning_decimal_to_bytesxx) +{ + char const* text = R"( + contract Foo { + bytes32 a = 7; + } + )"; + CHECK_WARNING(text, "Decimal literal assigned to bytesXX variable will be left-aligned."); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_assigning_hex_number_to_bytesxx) +{ + char const* text = R"( + contract Foo { + bytes32 a = 0x1234; + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(explicit_conversion_from_decimal_to_bytesxx) +{ + char const* text = R"( + contract Foo { + bytes32 a = bytes32(7); + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) { char const* text = R"( @@ -2284,6 +2381,16 @@ BOOST_AUTO_TEST_CASE(constant_struct) CHECK_ERROR(text, TypeError, "implemented"); } +BOOST_AUTO_TEST_CASE(address_is_constant) +{ + char const* text = R"( + contract C { + address constant x = 0x1212121212121212121212121212121212121212; + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(uninitialized_const_variable) { char const* text = R"( @@ -3708,12 +3815,12 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types) byte[2] memory a; byte[2] memory b; var k = true ? a : b; - k[0] = 0; //Avoid unused var warning + k[0] = byte(0); //Avoid unused var warning bytes memory e; bytes memory f; var l = true ? e : f; - l[0] = 0; // Avoid unused var warning + l[0] = byte(0); // Avoid unused var warning // fixed bytes bytes2 c; @@ -5445,6 +5552,25 @@ BOOST_AUTO_TEST_CASE(invalid_address_length) CHECK_WARNING(text, "checksum"); } +BOOST_AUTO_TEST_CASE(address_test_for_bug_in_implementation) +{ + // A previous implementation claimed the string would be an address + char const* text = R"( + contract AddrString { + address public test = "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c"; + } + )"; + CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type address"); + text = R"( + contract AddrString { + function f() returns (address) { + return "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c"; + } + } + )"; + CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type"); +} + BOOST_AUTO_TEST_CASE(early_exit_on_fatal_errors) { // This tests a crash that occured because we did not stop for fatal errors. @@ -5710,6 +5836,80 @@ BOOST_AUTO_TEST_CASE(pure_statement_check_for_regular_for_loop) success(text); } +BOOST_AUTO_TEST_CASE(warn_multiple_storage_storage_copies) +{ + char const* text = R"( + contract C { + struct S { uint a; uint b; } + S x; S y; + function f() { + (x, y) = (y, x); + } + } + )"; + CHECK_WARNING(text, "This assignment performs two copies to storage."); +} + +BOOST_AUTO_TEST_CASE(warn_multiple_storage_storage_copies_fill_right) +{ + char const* text = R"( + contract C { + struct S { uint a; uint b; } + S x; S y; + function f() { + (x, y, ) = (y, x, 1, 2); + } + } + )"; + CHECK_WARNING(text, "This assignment performs two copies to storage."); +} + +BOOST_AUTO_TEST_CASE(warn_multiple_storage_storage_copies_fill_left) +{ + char const* text = R"( + contract C { + struct S { uint a; uint b; } + S x; S y; + function f() { + (,x, y) = (1, 2, y, x); + } + } + )"; + CHECK_WARNING(text, "This assignment performs two copies to storage."); +} + +BOOST_AUTO_TEST_CASE(nowarn_swap_memory) +{ + char const* text = R"( + contract C { + struct S { uint a; uint b; } + function f() { + S memory x; + S memory y; + (x, y) = (y, x); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(nowarn_swap_storage_pointers) +{ + char const* text = R"( + contract C { + struct S { uint a; uint b; } + S x; S y; + function f() { + S storage x_local = x; + S storage y_local = y; + S storage z_local = x; + (x, y_local, x_local, z_local) = (y, x_local, y_local, y); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(warn_unused_local) { char const* text = R"( diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 35644a4d..be13d46b 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -189,37 +189,43 @@ BOOST_AUTO_TEST_CASE(basic_compilation) Json::Value contract = getContractResult(result, "fileA", "A"); BOOST_CHECK(contract.isObject()); BOOST_CHECK(contract["abi"].isArray()); - BOOST_CHECK(dev::jsonCompactPrint(contract["abi"]) == "[]"); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["abi"]), "[]"); BOOST_CHECK(contract["devdoc"].isObject()); - BOOST_CHECK(dev::jsonCompactPrint(contract["devdoc"]) == "{\"methods\":{}}"); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["devdoc"]), "{\"methods\":{}}"); BOOST_CHECK(contract["userdoc"].isObject()); - BOOST_CHECK(dev::jsonCompactPrint(contract["userdoc"]) == "{\"methods\":{}}"); + BOOST_CHECK_EQUAL(dev::jsonCompactPrint(contract["userdoc"]), "{\"methods\":{}}"); BOOST_CHECK(contract["evm"].isObject()); /// @TODO check evm.methodIdentifiers, legacyAssembly, bytecode, deployedBytecode BOOST_CHECK(contract["evm"]["bytecode"].isObject()); BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); - BOOST_CHECK(dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()) == - "60606040523415600b57fe5b5b60338060196000396000f30060606040525bfe00"); + BOOST_CHECK_EQUAL( + dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()), + "60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00" + ); BOOST_CHECK(contract["evm"]["assembly"].isString()); BOOST_CHECK(contract["evm"]["assembly"].asString().find( " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x60)\n jumpi(tag_1, iszero(callvalue))\n" - " invalid\ntag_1:\ntag_2:\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n" + " 0x0\n dup1\n revert\ntag_1:\ntag_2:\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n" " return\nstop\n\nsub_0: assembly {\n /* \"fileA\":0:14 contract A { } */\n" - " mstore(0x40, 0x60)\n tag_1:\n invalid\n\n" - " auxdata: 0xa165627a7a72305820") != std::string::npos); + " mstore(0x40, 0x60)\n tag_1:\n 0x0\n dup1\n revert\n\n" + " auxdata: 0xa165627a7a7230582") == 0); BOOST_CHECK(contract["evm"]["gasEstimates"].isObject()); - BOOST_CHECK(dev::jsonCompactPrint(contract["evm"]["gasEstimates"]) == - "{\"creation\":{\"codeDepositCost\":\"10200\",\"executionCost\":\"62\",\"totalCost\":\"10262\"}}"); + BOOST_CHECK_EQUAL( + dev::jsonCompactPrint(contract["evm"]["gasEstimates"]), + "{\"creation\":{\"codeDepositCost\":\"10800\",\"executionCost\":\"62\",\"totalCost\":\"10862\"}}" + ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); BOOST_CHECK(result["sources"].isObject()); BOOST_CHECK(result["sources"]["fileA"].isObject()); BOOST_CHECK(result["sources"]["fileA"]["legacyAST"].isObject()); - BOOST_CHECK(dev::jsonCompactPrint(result["sources"]["fileA"]["legacyAST"]) == + BOOST_CHECK_EQUAL( + dev::jsonCompactPrint(result["sources"]["fileA"]["legacyAST"]), "{\"attributes\":{\"absolutePath\":\"fileA\",\"exportedSymbols\":{\"A\":[1]}},\"children\":" "[{\"attributes\":{\"baseContracts\":[null],\"contractDependencies\":[null],\"contractKind\":\"contract\"," "\"documentation\":null,\"fullyImplemented\":true,\"linearizedBaseContracts\":[1],\"name\":\"A\",\"nodes\":[null],\"scope\":2}," - "\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}"); + "\"id\":1,\"name\":\"ContractDefinition\",\"src\":\"0:14:0\"}],\"id\":2,\"name\":\"SourceUnit\",\"src\":\"0:14:0\"}" + ); } BOOST_AUTO_TEST_SUITE_END() |