diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/fuzzer.cpp | 1 | ||||
-rw-r--r-- | test/libdevcore/MiniMoustache.cpp | 127 | ||||
-rw-r--r-- | test/libdevcore/UTF8.cpp | 216 | ||||
-rw-r--r-- | test/liblll/EndToEndTest.cpp | 20 | ||||
-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 |
9 files changed, 657 insertions, 26 deletions
diff --git a/test/fuzzer.cpp b/test/fuzzer.cpp index 053d880f..cf99755f 100644 --- a/test/fuzzer.cpp +++ b/test/fuzzer.cpp @@ -152,7 +152,6 @@ void testCompiler() "Exception during compilation", "Unknown exception during compilation", "Unknown exception while generating contract data output", - "Unknown exception while generating formal method output", "Unknown exception while generating source name output", "Unknown error while generating JSON" }); diff --git a/test/libdevcore/MiniMoustache.cpp b/test/libdevcore/MiniMoustache.cpp new file mode 100644 index 00000000..84149173 --- /dev/null +++ b/test/libdevcore/MiniMoustache.cpp @@ -0,0 +1,127 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Unit tests for the mini moustache class. + */ + +#include <libdevcore/Whiskers.h> + +#include "../TestHelper.h" + +using namespace std; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(WhiskersTest) + +BOOST_AUTO_TEST_CASE(no_templates) +{ + string templ = "this text does not contain templates"; + BOOST_CHECK_EQUAL(Whiskers(templ).render(), templ); +} + +BOOST_AUTO_TEST_CASE(basic_replacement) +{ + string templ = "a <b> x <c> -> <d>."; + string result = Whiskers(templ) + ("b", "BE") + ("c", "CE") + ("d", "DE") + .render(); + BOOST_CHECK_EQUAL(result, "a BE x CE -> DE."); +} + +BOOST_AUTO_TEST_CASE(tag_unavailable) +{ + string templ = "<b>"; + Whiskers m(templ); + BOOST_CHECK_THROW(m.render(), WhiskersError); +} + +BOOST_AUTO_TEST_CASE(complicated_replacement) +{ + string templ = "a <b> x <complicated> \n <nes<ted>>."; + string result = Whiskers(templ) + ("b", "BE") + ("complicated", "CO<M>PL") + ("nes<ted", "NEST") + .render(); + BOOST_CHECK_EQUAL(result, "a BE x CO<M>PL \n NEST>."); +} + +BOOST_AUTO_TEST_CASE(non_existing_list) +{ + string templ = "a <#b></b>"; + Whiskers m(templ); + BOOST_CHECK_THROW(m.render(), WhiskersError); +} + +BOOST_AUTO_TEST_CASE(empty_list) +{ + string templ = "a <#b></b>x"; + string result = Whiskers(templ)("b", vector<Whiskers::StringMap>{}).render(); + BOOST_CHECK_EQUAL(result, "a x"); +} + +BOOST_AUTO_TEST_CASE(list) +{ + string templ = "a<#b>( <g> - <h> )</b>x"; + vector<map<string, string>> list(2); + list[0]["g"] = "GE"; + list[0]["h"] = "H"; + list[1]["g"] = "2GE"; + list[1]["h"] = "2H"; + string result = Whiskers(templ)("b", list).render(); + BOOST_CHECK_EQUAL(result, "a( GE - H )( 2GE - 2H )x"); +} + +BOOST_AUTO_TEST_CASE(recursive_list) +{ + // Check that templates resulting from lists are not expanded again + string templ = "a<#b> 1<g>3 </b><x>"; + vector<map<string, string>> list(1); + list[0]["g"] = "<x>"; + string result = Whiskers(templ)("x", "X")("b", list).render(); + BOOST_CHECK_EQUAL(result, "a 1<x>3 X"); +} + +BOOST_AUTO_TEST_CASE(list_can_access_upper) +{ + string templ = "<#b>(<a>)</b>"; + vector<map<string, string>> list(2); + Whiskers m(templ); + string result = m("a", "A")("b", list).render(); + BOOST_CHECK_EQUAL(result, "(A)(A)"); +} + +BOOST_AUTO_TEST_CASE(parameter_collision) +{ + string templ = "a <#b></b>"; + vector<map<string, string>> list(1); + list[0]["a"] = "x"; + Whiskers m(templ); + m("a", "X")("b", list); + BOOST_CHECK_THROW(m.render(), WhiskersError); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} diff --git a/test/libdevcore/UTF8.cpp b/test/libdevcore/UTF8.cpp new file mode 100644 index 00000000..719ada72 --- /dev/null +++ b/test/libdevcore/UTF8.cpp @@ -0,0 +1,216 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Unit tests for UTF-8 validation. + */ + +#include <libdevcore/CommonData.h> +#include <libdevcore/UTF8.h> + +#include "../TestHelper.h" + +using namespace std; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(UTF8) + +namespace { + +bool isValidUTF8(string const& _value) +{ + size_t pos; + return validateUTF8(asString(fromHex(_value)), pos); +} + +bool isInvalidUTF8(string const& _value, size_t _expectedPos) +{ + size_t pos; + if (validateUTF8(asString(fromHex(_value)), pos)) + return false; + if (pos != _expectedPos) + return false; + return true; +} + +} + +BOOST_AUTO_TEST_CASE(valid) +{ + BOOST_CHECK(isValidUTF8("00")); + BOOST_CHECK(isValidUTF8("20")); + BOOST_CHECK(isValidUTF8("7f")); + BOOST_CHECK(isValidUTF8("c281")); + BOOST_CHECK(isValidUTF8("df81")); + BOOST_CHECK(isValidUTF8("e0a081")); + BOOST_CHECK(isValidUTF8("e18081")); + BOOST_CHECK(isValidUTF8("ec8081")); + BOOST_CHECK(isValidUTF8("ed8081")); + BOOST_CHECK(isValidUTF8("ee8081")); + BOOST_CHECK(isValidUTF8("ef8081")); + BOOST_CHECK(isValidUTF8("f0908081")); + BOOST_CHECK(isValidUTF8("f3808081")); + BOOST_CHECK(isValidUTF8("f2808081")); + BOOST_CHECK(isValidUTF8("f3808081")); + BOOST_CHECK(isValidUTF8("f48e8081")); +} + +BOOST_AUTO_TEST_CASE(invalid) +{ + // anything between 0x80 and 0xc0 is disallowed + BOOST_CHECK(isInvalidUTF8("80", 0)); // invalid per table 3.6 + BOOST_CHECK(isInvalidUTF8("a0", 0)); // invalid per table 3.6 + BOOST_CHECK(isInvalidUTF8("c0", 0)); // invalid per table 3.7 + BOOST_CHECK(isInvalidUTF8("c1", 0)); // invalid per table 3.7 + BOOST_CHECK(isInvalidUTF8("c2", 0)); // too short (position is reported as the first byte) + BOOST_CHECK(isInvalidUTF8("e08081", 2)); // e0 must be followed by >= a0 + BOOST_CHECK(isInvalidUTF8("e180", 0)); // too short + BOOST_CHECK(isInvalidUTF8("ec80", 0)); // too short + BOOST_CHECK(isInvalidUTF8("f08f8001", 2)); // f0 must be followed by >= 90 + BOOST_CHECK(isInvalidUTF8("f18080", 0)); // too short + BOOST_CHECK(isInvalidUTF8("f4908081", 2)); // f4 must be followed by < 90 + // anything above 0xf7 is disallowed + BOOST_CHECK(isInvalidUTF8("f8", 0)); // invalid per table 3.7 + BOOST_CHECK(isInvalidUTF8("f9", 0)); // invalid per table 3.7 +} + +BOOST_AUTO_TEST_CASE(corpus) +{ + string source = R"( +κόσμε + +hélló + +Ā ā Ă ă Ą ą + +ƀ Ɓ Ƃ ƃ Ƅ ƅ + +ɐ ɑ ɒ ɓ ɔ ɕ + +ʰ ʱ ʲ ʳ ʴ ʵ + +̀ ́ ̂ ̃ ̄ ̅ + +ϩ Ϫ ϫ Ϭ ϭ Ϯ + +Ё Ђ Ѓ Є Ѕ І + +Ա Բ Գ Դ Ե Զ + + ק ר ש ת װ ױ + +ځ ڂ ڃ ڄ څ چ + +ऑ ऒ ओ औ क ख + +ও ঔ ক খ গ ঘ + +ਘ ਙ ਚ ਛ ਜ ਝ + +ઓ ઔ ક ખ ગ ઘ + +ଗ ଘ ଙ ଚ ଛ ଜ + +ஔ க ங ச ஜ ஞ + +ఎ ఏ ఐ ఒ ఓ ఔ + +ಓ ಔ ಕ ಖ ಗ ಘ + +ഐ ഒ ഓ ഔ ക + +ฒ ณ ด ต ถ ท + +ມ ຢ ຣ ລ ວ ສ + +༄ ༅ ༆ ༇ ༈ ༉ + +Ⴑ Ⴒ Ⴓ Ⴔ Ⴕ Ⴖ + +ᄌ ᄍ ᄎ ᄏ ᄐ + +Ḕ ḕ Ḗ ḗ Ḙ ḙ Ḛ + +ἐ ἑ ἒ ἓ ἔ ἕ + +₠ ₡ ₢ ₣ ₤ ₥ + +⃐ ⃑ ⃒ ⃓ ⃔ ⃕ ⃖ ⃗ ⃘ ⃙ ⃚ + +ℋ ℌ ℍ ℎ ℏ ℐ ℑ + +⅓ ⅔ ⅕ ⅖ ⅗ + +∬ ∭ ∮ ∯ ∰ + +⌖ ⌗ ⌘ ⌙ ⌚ ⌛ + +␀ ␁ ␂ ␃ ␄ ␅ + +⑀ ⑁ ⑂ ⑃ ⑄ + +① ② ③ ④ ⑤ + +╘ ╙ ╚ ╛ ╜ ╝ + +▁ ▂ ▃ ▄ ▅ ▆ + +▤ ▥ ▦ ▧ ▨ + +♔ ♕ ♖ ♗ ♘ ♙ + +✈ ✉ ✌ ✍ ✎ + +ぁ あ ぃ い ぅ + +ァ ア ィ イ ゥ + +ㄅ ㄆ ㄇ ㄈ ㄉ + +ㄱ ㄲ ㄳ ㄴ ㄵ + +㆚ ㆛ ㆜ ㆝ ㆞ + +㈀ ㈁ ㈂ ㈃ ㈄ + +㌀ ㌁ ㌂ ㌃ ㌄ + +乺 乻 乼 乽 乾 + +걺 걻 걼 걽 걾 + +豈 更 車 賈 滑 + +שּׁ שּׂ אַ אָ אּ + +ﮄ ﮅ ﮆ ﮇ ﮈ ﮉ + + ﺵ ﺶ ﺷ ﺸ + +「 」 、 ・ ヲ ァ ィ ゥ + )"; + size_t pos; + BOOST_CHECK(validateUTF8(source, pos)); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 02d024a4..3037b14b 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -57,6 +57,26 @@ BOOST_AUTO_TEST_CASE(panic) BOOST_REQUIRE(m_output.empty()); } +BOOST_AUTO_TEST_CASE(variables) +{ + char const* sourceCode = R"( + (returnlll + (seq + (set 'x 1) + (set 'y 2) + ;; this should equal to 3 + (set 'z (add (get 'x) (get 'y))) + ;; overwriting it here + (set 'y 4) + ;; each variable has a 32 byte slot, starting from memory location 0x80 + ;; variable addresses can also be retrieved by x or (ref 'x) + (set 'k (add (add (ref 'x) (ref 'y)) z)) + (return (add (add (get 'x) (add (get 'y) (get 'z))) (get 'k))))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(488))); +} + BOOST_AUTO_TEST_CASE(when) { char const* sourceCode = R"( 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() |