mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Some more ABI tests.
This commit is contained in:
		
							parent
							
								
									279e64ae75
								
							
						
					
					
						commit
						95acbc7a9f
					
				| @ -46,6 +46,7 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) | |||||||
| 	if (dev::test::Options::get().disableIPC) | 	if (dev::test::Options::get().disableIPC) | ||||||
| 	{ | 	{ | ||||||
| 		for (auto suite: { | 		for (auto suite: { | ||||||
|  | 			"ABIEncoderTest", | ||||||
| 			"SolidityAuctionRegistrar", | 			"SolidityAuctionRegistrar", | ||||||
| 			"SolidityFixedFeeRegistrar", | 			"SolidityFixedFeeRegistrar", | ||||||
| 			"SolidityWallet", | 			"SolidityWallet", | ||||||
|  | |||||||
							
								
								
									
										259
									
								
								test/libsolidity/ABIEncoderTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								test/libsolidity/ABIEncoderTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,259 @@ | |||||||
|  | /*
 | ||||||
|  | 	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 Solidity's ABI encoder. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <functional> | ||||||
|  | #include <string> | ||||||
|  | #include <tuple> | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | #include <libsolidity/interface/Exceptions.h> | ||||||
|  | #include <test/libsolidity/SolidityExecutionFramework.h> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | using namespace std::placeholders; | ||||||
|  | using namespace dev::test; | ||||||
|  | 
 | ||||||
|  | namespace dev | ||||||
|  | { | ||||||
|  | namespace solidity | ||||||
|  | { | ||||||
|  | namespace test | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | #define REQUIRE_LOG_DATA(DATA) do { \ | ||||||
|  | 	BOOST_REQUIRE_EQUAL(m_logs.size(), 1); \ | ||||||
|  | 	BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); \ | ||||||
|  | 	BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(DATA)); \ | ||||||
|  | } while (false) | ||||||
|  | 
 | ||||||
|  | BOOST_FIXTURE_TEST_SUITE(ABIEncoderTest, SolidityExecutionFramework) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(value_types) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			event E(uint a, uint16 b, uint24 c, int24 d, bytes3 x, bool, C); | ||||||
|  | 			function f() { | ||||||
|  | 				bytes6 x = hex"1bababababa2"; | ||||||
|  | 				bool b; | ||||||
|  | 				assembly { b := 7 } | ||||||
|  | 				C c; | ||||||
|  | 				assembly { c := sub(0, 5) } | ||||||
|  | 				E(10, uint16(uint256(-2)), uint24(0x12121212), int24(int256(-1)), bytes3(x), b, c); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f()"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs( | ||||||
|  | 		10, u256(65534), u256(0x121212), u256(-1), string("\x1b\xab\xab"), true, u160(u256(-5)) | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(string_literal) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			event E(string, bytes20, string); | ||||||
|  | 			function f() { | ||||||
|  | 				E("abcdef", "abcde", "abcdefabcdefgehabcabcasdfjklabcdefabcedefghabcabcasdfjklabcdefabcdefghabcabcasdfjklabcdeefabcdefghabcabcasdefjklabcdefabcdefghabcabcasdfjkl"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f()"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs( | ||||||
|  | 		0x60, string("abcde"), 0xa0, | ||||||
|  | 		6, string("abcdef"), | ||||||
|  | 		0x8b, string("abcdefabcdefgehabcabcasdfjklabcdefabcedefghabcabcasdfjklabcdefabcdefghabcabcasdfjklabcdeefabcdefghabcabcasdefjklabcdefabcdefghabcabcasdfjkl") | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(enum_type_cleanup) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			enum E { A, B } | ||||||
|  | 			function f(uint x) returns (E en) { | ||||||
|  | 				assembly { en := x } | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	BOOST_CHECK(callContractFunction("f(uint256)", 0) == encodeArgs(0)); | ||||||
|  | 	BOOST_CHECK(callContractFunction("f(uint256)", 1) == encodeArgs(1)); | ||||||
|  | 	BOOST_CHECK(callContractFunction("f(uint256)", 2) == encodeArgs()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(conversion) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			event E(bytes4, bytes4, uint16, uint8, int16, int8); | ||||||
|  | 			function f() { | ||||||
|  | 				bytes2 x; assembly { x := 0xf1f2f3f400000000000000000000000000000000000000000000000000000000 } | ||||||
|  | 				uint8 a; | ||||||
|  | 				uint16 b = 0x1ff; | ||||||
|  | 				int8 c; | ||||||
|  | 				int16 d; | ||||||
|  | 				assembly { a := sub(0, 1) c := 0x0101ff d := 0xff01 } | ||||||
|  | 				E(10, x, a, uint8(b), c, int8(d)); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f()"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs( | ||||||
|  | 		string(3, 0) + string("\x0a"), string("\xf1\xf2"), | ||||||
|  | 		0xff, 0xff, u256(-1), u256(1) | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(storage_byte_array) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			bytes short; | ||||||
|  | 			bytes long; | ||||||
|  | 			event E(bytes s, bytes l); | ||||||
|  | 			function f() { | ||||||
|  | 				short = "123456789012345678901234567890a"; | ||||||
|  | 				long = "ffff123456789012345678901234567890afffffffff123456789012345678901234567890a"; | ||||||
|  | 				E(short, long); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f()"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs( | ||||||
|  | 		0x40, 0x80, | ||||||
|  | 		31, string("123456789012345678901234567890a"), | ||||||
|  | 		75, string("ffff123456789012345678901234567890afffffffff123456789012345678901234567890a") | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(storage_array) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			address[3] addr; | ||||||
|  | 			event E(address[3] a); | ||||||
|  | 			function f() { | ||||||
|  | 				assembly { | ||||||
|  | 					sstore(0, sub(0, 1)) | ||||||
|  | 					sstore(1, sub(0, 2)) | ||||||
|  | 					sstore(2, sub(0, 3)) | ||||||
|  | 				} | ||||||
|  | 				E(addr); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f()"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs(u160(-1), u160(-2), u160(-3))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(storage_array_dyn) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			address[] addr; | ||||||
|  | 			event E(address[] a); | ||||||
|  | 			function f() { | ||||||
|  | 				addr.push(1); | ||||||
|  | 				addr.push(2); | ||||||
|  | 				addr.push(3); | ||||||
|  | 				E(addr); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f()"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs(0x20, 3, u160(1), u160(2), u160(3))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(storage_array_compact) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			int72[] x; | ||||||
|  | 			event E(int72[]); | ||||||
|  | 			function f() { | ||||||
|  | 				x.push(-1); | ||||||
|  | 				x.push(2); | ||||||
|  | 				x.push(-3); | ||||||
|  | 				x.push(4); | ||||||
|  | 				x.push(-5); | ||||||
|  | 				x.push(6); | ||||||
|  | 				x.push(-7); | ||||||
|  | 				x.push(8); | ||||||
|  | 				E(x); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f()"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs( | ||||||
|  | 		0x20, 8, u256(-1), 2, u256(-3), 4, u256(-5), 6, u256(-7), 8 | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(external_function) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			event E(function(uint) external returns (uint), function(uint) external returns (uint)); | ||||||
|  | 			function(uint) external returns (uint) g; | ||||||
|  | 			function f(uint) returns (uint) { | ||||||
|  | 				g = this.f; | ||||||
|  | 				E(this.f, g); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f(uint256)"); | ||||||
|  | 	string functionIdF = asString(m_contractAddress.ref()) + asString(FixedHash<4>(dev::keccak256("f(uint256)")).ref()); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs(functionIdF, functionIdF)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(external_function_cleanup) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract C { | ||||||
|  | 			event E(function(uint) external returns (uint), function(uint) external returns (uint)); | ||||||
|  | 			// This test relies on the fact that g is stored in slot zero.
 | ||||||
|  | 			function(uint) external returns (uint) g; | ||||||
|  | 			function f(uint) returns (uint) { | ||||||
|  | 				function(uint) external returns (uint)[1] memory h; | ||||||
|  | 				assembly { sstore(0, sub(0, 1)) mstore(h, sub(0, 1)) } | ||||||
|  | 				E(h[0], g); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("f(uint256)"); | ||||||
|  | 	REQUIRE_LOG_DATA(encodeArgs(string(24, char(-1)), string(24, char(-1)))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | } | ||||||
|  | } // end namespaces
 | ||||||
| @ -3157,6 +3157,31 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data_from_storage) | |||||||
| 	BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)"))); | 	BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)"))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract ClientReceipt { | ||||||
|  | 			bytes x; | ||||||
|  | 			event Deposit(uint fixeda, bytes dynx, uint fixedb); | ||||||
|  | 			function deposit() { | ||||||
|  | 				x.length = 31; | ||||||
|  | 				x[0] = "A"; | ||||||
|  | 				x[1] = "B"; | ||||||
|  | 				x[2] = "C"; | ||||||
|  | 				x[30] = "Z"; | ||||||
|  | 				Deposit(10, x, 15); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	callContractFunction("deposit()"); | ||||||
|  | 	BOOST_REQUIRE_EQUAL(m_logs.size(), 1); | ||||||
|  | 	BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); | ||||||
|  | 	BOOST_CHECK(m_logs[0].data == encodeArgs(10, 0x60, 15, 31, string("ABC") + string(27, 0) + "Z")); | ||||||
|  | 	BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); | ||||||
|  | 	BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)"))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(event_indexed_string) | BOOST_AUTO_TEST_CASE(event_indexed_string) | ||||||
| { | { | ||||||
| 	char const* sourceCode = R"( | 	char const* sourceCode = R"( | ||||||
| @ -4402,6 +4427,75 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct) | |||||||
| 	BOOST_CHECK(storageEmpty(m_contractAddress)); | 	BOOST_CHECK(storageEmpty(m_contractAddress)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(array_copy_storage_abi) | ||||||
|  | { | ||||||
|  | 	// NOTE: This does not really test copying from storage to ABI directly,
 | ||||||
|  | 	// because it will always copy to memory first.
 | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract c { | ||||||
|  | 			uint8[] x; | ||||||
|  | 			uint16[] y; | ||||||
|  | 			uint24[] z; | ||||||
|  | 			function test1() returns (uint8[]) { | ||||||
|  | 				for (uint i = 0; i < 101; ++i) | ||||||
|  | 					x.push(uint8(i)); | ||||||
|  | 				return x; | ||||||
|  | 			} | ||||||
|  | 			function test2() returns (uint16[]) { | ||||||
|  | 				for (uint i = 0; i < 101; ++i) | ||||||
|  | 					y.push(uint16(i)); | ||||||
|  | 				return y; | ||||||
|  | 			} | ||||||
|  | 			function test3() returns (uint24[]) { | ||||||
|  | 				for (uint i = 0; i < 101; ++i) | ||||||
|  | 					z.push(uint24(i)); | ||||||
|  | 				return z; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	bytes valueSequence; | ||||||
|  | 	for (size_t i = 0; i < 101; ++i) | ||||||
|  | 		valueSequence += toBigEndian(u256(i)); | ||||||
|  | 	BOOST_CHECK(callContractFunction("test1()") == encodeArgs(0x20, 101) + valueSequence); | ||||||
|  | 	BOOST_CHECK(callContractFunction("test2()") == encodeArgs(0x20, 101) + valueSequence); | ||||||
|  | 	BOOST_CHECK(callContractFunction("test3()") == encodeArgs(0x20, 101) + valueSequence); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(array_copy_storage_abi_signed) | ||||||
|  | { | ||||||
|  | 	// NOTE: This does not really test copying from storage to ABI directly,
 | ||||||
|  | 	// because it will always copy to memory first.
 | ||||||
|  | 	char const* sourceCode = R"( | ||||||
|  | 		contract c { | ||||||
|  | 			int16[] x; | ||||||
|  | 			function test() returns (int16[]) { | ||||||
|  | 				x.push(int16(-1)); | ||||||
|  | 				x.push(int16(-1)); | ||||||
|  | 				x.push(int16(8)); | ||||||
|  | 				x.push(int16(-16)); | ||||||
|  | 				x.push(int16(-2)); | ||||||
|  | 				x.push(int16(6)); | ||||||
|  | 				x.push(int16(8)); | ||||||
|  | 				x.push(int16(-1)); | ||||||
|  | 				return x; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	)"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	bytes valueSequence; | ||||||
|  | 	BOOST_CHECK(callContractFunction("test()") == encodeArgs(0x20, 8, | ||||||
|  | 		u256(-1), | ||||||
|  | 		u256(-1), | ||||||
|  | 		u256(8), | ||||||
|  | 		u256(-16), | ||||||
|  | 		u256(-2), | ||||||
|  | 		u256(6), | ||||||
|  | 		u256(8), | ||||||
|  | 		u256(-1) | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(array_push) | BOOST_AUTO_TEST_CASE(array_push) | ||||||
| { | { | ||||||
| 	char const* sourceCode = R"( | 	char const* sourceCode = R"( | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user