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) | ||||
| 	{ | ||||
| 		for (auto suite: { | ||||
| 			"ABIEncoderTest", | ||||
| 			"SolidityAuctionRegistrar", | ||||
| 			"SolidityFixedFeeRegistrar", | ||||
| 			"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_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) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| @ -4402,6 +4427,75 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct) | ||||
| 	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) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user