mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #10448 from ethereum/fixedhash
Add comprehensive tests for FixedHash
This commit is contained in:
		
						commit
						dc5f7a7405
					
				| @ -48,6 +48,7 @@ public: | ||||
| 
 | ||||
| 	/// The size of the container.
 | ||||
| 	enum { size = N }; | ||||
| 	static_assert(N != 0); | ||||
| 
 | ||||
| 	/// Method to convert from a string.
 | ||||
| 	enum ConstructFromStringType { FromHex, FromBinary }; | ||||
| @ -59,7 +60,13 @@ public: | ||||
| 	explicit FixedHash() { m_data.fill(0); } | ||||
| 
 | ||||
| 	/// Construct from another hash, filling with zeroes or cropping as necessary.
 | ||||
| 	template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; } | ||||
| 	template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) | ||||
| 	{ | ||||
| 		m_data.fill(0); | ||||
| 		unsigned c = std::min(M, N); | ||||
| 		for (unsigned i = 0; i < c; ++i) | ||||
| 			m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; | ||||
| 	} | ||||
| 
 | ||||
| 	/// Convert from the corresponding arithmetic type.
 | ||||
| 	FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } | ||||
| @ -104,8 +111,10 @@ public: | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/// Explicitly construct, copying from a  string.
 | ||||
| 	explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : solidity::util::asBytes(_s), _ht) {} | ||||
| 	/// Explicitly construct, copying from a string.
 | ||||
| 	explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): | ||||
| 		FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : solidity::util::asBytes(_s), _ht) | ||||
| 	{} | ||||
| 
 | ||||
| 	/// Convert to arithmetic type.
 | ||||
| 	operator Arith() const { return fromBigEndian<Arith>(m_data); } | ||||
| @ -114,7 +123,16 @@ public: | ||||
| 	bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } | ||||
| 	bool operator!=(FixedHash const& _c) const { return m_data != _c.m_data; } | ||||
| 	/// Required to sort objects of this type or use them as map keys.
 | ||||
| 	bool operator<(FixedHash const& _c) const { for (unsigned i = 0; i < N; ++i) if (m_data[i] < _c.m_data[i]) return true; else if (m_data[i] > _c.m_data[i]) return false; return false; } | ||||
| 	bool operator<(FixedHash const& _c) const { | ||||
| 		for (unsigned i = 0; i < N; ++i) | ||||
| 		{ | ||||
| 			if (m_data[i] < _c.m_data[i]) | ||||
| 				return true; | ||||
| 			else if (m_data[i] > _c.m_data[i]) | ||||
| 				return false; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	/// @returns a particular byte from the hash.
 | ||||
| 	uint8_t& operator[](unsigned _i) { return m_data[_i]; } | ||||
|  | ||||
| @ -29,6 +29,7 @@ detect_stray_source_files("${contracts_sources}" "contracts/") | ||||
| set(libsolutil_sources | ||||
|     libsolutil/Checksum.cpp | ||||
|     libsolutil/CommonData.cpp | ||||
|     libsolutil/FixedHash.cpp | ||||
|     libsolutil/IndentedWriter.cpp | ||||
|     libsolutil/IpfsHash.cpp | ||||
|     libsolutil/IterateReplacing.cpp | ||||
|  | ||||
							
								
								
									
										272
									
								
								test/libsolutil/FixedHash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								test/libsolutil/FixedHash.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,272 @@ | ||||
| /*
 | ||||
| 	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 FixedHash. | ||||
|  */ | ||||
| 
 | ||||
| #include <libsolutil/FixedHash.h> | ||||
| 
 | ||||
| #include <boost/test/unit_test.hpp> | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <sstream> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| namespace solidity::util::test | ||||
| { | ||||
| 
 | ||||
| static_assert(std::is_same<h160, FixedHash<20>>()); | ||||
| static_assert(std::is_same<h256, FixedHash<32>>()); | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE(FixedHashTest) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(default_constructor) | ||||
| { | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<1>{}.hex(), | ||||
| 		"00" | ||||
| 	); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<1>{}.size, | ||||
| 		1 | ||||
| 	); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<8>{}.hex(), | ||||
| 		"0000000000000000" | ||||
| 	); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<8>{}.size, | ||||
| 		8 | ||||
| 	); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<20>{}.hex(), | ||||
| 		"0000000000000000000000000000000000000000" | ||||
| 	); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<20>{}.size, | ||||
| 		20 | ||||
| 	); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<32>{}.hex(), | ||||
| 		"0000000000000000000000000000000000000000000000000000000000000000" | ||||
| 	); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		FixedHash<32>{}.size, | ||||
| 		32 | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(bytes_constructor) | ||||
| { | ||||
| 	FixedHash<8> a(bytes{}); | ||||
| 	BOOST_CHECK_EQUAL(a.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(a.hex(), "0000000000000000"); | ||||
| 
 | ||||
| 	FixedHash<8> b(bytes{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}); | ||||
| 	BOOST_CHECK_EQUAL(b.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(b.hex(), "1122334455667788"); | ||||
| 
 | ||||
| 	// TODO: short input, this should fail
 | ||||
| 	FixedHash<8> c(bytes{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); | ||||
| 	BOOST_CHECK_EQUAL(c.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(c.hex(), "0000000000000000"); | ||||
| 
 | ||||
| 	// TODO: oversized input, this should fail
 | ||||
| 	FixedHash<8> d(bytes{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}); | ||||
| 	BOOST_CHECK_EQUAL(d.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(d.hex(), "0000000000000000"); | ||||
| } | ||||
| 
 | ||||
| // TODO: add FixedHash(bytesConstRef) constructor
 | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(string_constructor_fromhex) | ||||
| { | ||||
| 	// TODO: this tests the default settings ConstructFromStringType::fromHex, ConstructFromHashType::FailIfDifferent
 | ||||
| 	//       should test other options too
 | ||||
| 
 | ||||
| 	FixedHash<8> a(""); | ||||
| 	BOOST_CHECK_EQUAL(a.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(a.hex(), "0000000000000000"); | ||||
| 
 | ||||
| 	FixedHash<8> b("1122334455667788"); | ||||
| 	BOOST_CHECK_EQUAL(b.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(b.hex(), "1122334455667788"); | ||||
| 
 | ||||
| 	FixedHash<8> c("0x1122334455667788"); | ||||
| 	BOOST_CHECK_EQUAL(c.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(c.hex(), "1122334455667788"); | ||||
| 
 | ||||
| 	// TODO: short input, this should fail
 | ||||
| 	FixedHash<8> d("112233445566"); | ||||
| 	BOOST_CHECK_EQUAL(d.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(d.hex(), "0000000000000000"); | ||||
| 
 | ||||
| 	// TODO: oversized input, this should fail
 | ||||
| 	FixedHash<8> e("112233445566778899"); | ||||
| 	BOOST_CHECK_EQUAL(e.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(e.hex(), "0000000000000000"); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(string_constructor_frombytes) | ||||
| { | ||||
| 
 | ||||
| 	FixedHash<8> b("", FixedHash<8>::FromBinary); | ||||
| 	BOOST_CHECK_EQUAL(b.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(b.hex(), "0000000000000000"); | ||||
| 
 | ||||
| 	FixedHash<8> c("abcdefgh", FixedHash<8>::FromBinary); | ||||
| 	BOOST_CHECK_EQUAL(c.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(c.hex(), "6162636465666768"); | ||||
| 
 | ||||
| 	// TODO: short input, this should fail
 | ||||
| 	FixedHash<8> d("abcdefg", FixedHash<8>::FromBinary); | ||||
| 	BOOST_CHECK_EQUAL(d.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(d.hex(), "0000000000000000"); | ||||
| 
 | ||||
| 	// TODO: oversized input, this should fail
 | ||||
| 	FixedHash<8> e("abcdefghi", FixedHash<8>::FromBinary); | ||||
| 	BOOST_CHECK_EQUAL(e.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(e.hex(), "0000000000000000"); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(converting_constructor) | ||||
| { | ||||
| 	// Truncation
 | ||||
| 	FixedHash<8> a = FixedHash<8>(FixedHash<12>("112233445566778899001122")); | ||||
| 	BOOST_CHECK_EQUAL(a.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(a.hex(), "1122334455667788"); | ||||
| 
 | ||||
| 	// Left-aligned extension
 | ||||
| 	FixedHash<12> b = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignLeft); | ||||
| 	BOOST_CHECK_EQUAL(b.size, 12); | ||||
| 	BOOST_CHECK_EQUAL(b.hex(), "112233445566778800000000"); | ||||
| 
 | ||||
| 	// Right-aligned extension
 | ||||
| 	FixedHash<12> c = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignRight); | ||||
| 	BOOST_CHECK_EQUAL(c.size, 12); | ||||
| 	BOOST_CHECK_EQUAL(c.hex(), "000000001122334455667788"); | ||||
| 
 | ||||
| 	// Default setting
 | ||||
| 	FixedHash<12> d = FixedHash<12>(FixedHash<8>("1122334455667788")); | ||||
| 	BOOST_CHECK_EQUAL(d, b); | ||||
| 
 | ||||
| 	// FailIfDifferent setting
 | ||||
| 	// TODO: Shouldn't this throw?
 | ||||
| 	FixedHash<12> e = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::FailIfDifferent); | ||||
| 	BOOST_CHECK_EQUAL(e, b); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(arith_constructor) | ||||
| { | ||||
| 	FixedHash<20> a(u160(0x1234)); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		a.hex(), | ||||
| 		"0000000000000000000000000000000000001234" | ||||
| 	); | ||||
| 
 | ||||
| 	FixedHash<32> b(u256(0x12340000)); | ||||
| 	BOOST_CHECK_EQUAL( | ||||
| 		b.hex(), | ||||
| 		"0000000000000000000000000000000000000000000000000000000012340000" | ||||
| 	); | ||||
| 
 | ||||
| 	// NOTE: size-mismatched constructor is not available
 | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(to_arith) | ||||
| { | ||||
| 	FixedHash<20> a{}; | ||||
| 	BOOST_CHECK_EQUAL(u160(a), 0); | ||||
| 
 | ||||
| 	FixedHash<32> b("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); | ||||
| 	BOOST_CHECK_EQUAL(u256(b), u256("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(comparison) | ||||
| { | ||||
| 	FixedHash<32> a("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); | ||||
| 	FixedHash<32> b("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); | ||||
| 	FixedHash<32> c("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a471"); | ||||
| 	FixedHash<32> d("233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470c5d2460186f7"); | ||||
| 
 | ||||
| 	BOOST_CHECK(a == a); | ||||
| 	BOOST_CHECK(b == b); | ||||
| 	BOOST_CHECK(a == b); | ||||
| 	BOOST_CHECK(b == a); | ||||
| 	BOOST_CHECK(a != c); | ||||
| 	BOOST_CHECK(c != a); | ||||
| 	BOOST_CHECK(a != d); | ||||
| 	BOOST_CHECK(d != a); | ||||
| 
 | ||||
| 	// Only equal size comparison is supported.
 | ||||
| 	BOOST_CHECK(FixedHash<8>{} == FixedHash<8>{}); | ||||
| 	BOOST_CHECK(FixedHash<32>{} != b); | ||||
| 
 | ||||
| 	// Only equal size less than comparison is supported.
 | ||||
| 	BOOST_CHECK(!(a < b)); | ||||
| 	BOOST_CHECK(d < c); | ||||
| 	BOOST_CHECK(FixedHash<32>{} < a); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(indexing) | ||||
| { | ||||
| 	// NOTE: uses std::array, so "Accessing a nonexistent element through this operator is undefined behavior."
 | ||||
| 
 | ||||
| 	FixedHash<32> a("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); | ||||
| 	BOOST_CHECK_EQUAL(a[0], 0xc5); | ||||
| 	BOOST_CHECK_EQUAL(a[1], 0xd2); | ||||
| 	BOOST_CHECK_EQUAL(a[31], 0x70); | ||||
| 	a[0] = 0xff; | ||||
| 	a[31] = 0x54; | ||||
| 	BOOST_CHECK_EQUAL(a[0], 0xff); | ||||
| 	BOOST_CHECK_EQUAL(a[1], 0xd2); | ||||
| 	BOOST_CHECK_EQUAL(a[31], 0x54); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(misc) | ||||
| { | ||||
| 	FixedHash<32> a("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); | ||||
| 
 | ||||
| 	uint8_t* mut_a = a.data(); | ||||
| 	uint8_t const* const_a = a.data(); | ||||
| 	BOOST_CHECK_EQUAL(mut_a, const_a); | ||||
| 	BOOST_CHECK_EQUAL(memcmp(mut_a, const_a, a.size), 0); | ||||
| 
 | ||||
| 	bytes bytes_a = a.asBytes(); | ||||
| 	bytesRef bytesref_a = a.ref(); | ||||
| 	bytesConstRef bytesconstref_a = a.ref(); | ||||
| 
 | ||||
| 	// There's no printing for bytesRef/bytesConstRef
 | ||||
| 	BOOST_CHECK(bytes(a.data(), a.data() + a.size) == bytes_a); | ||||
| 	BOOST_CHECK(bytesRef(a.data(), a.size) == bytesref_a); | ||||
| 	BOOST_CHECK(bytesConstRef(a.data(), a.size) == bytesconstref_a); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(tostream) | ||||
| { | ||||
| 	std::ostringstream out; | ||||
| 	out << FixedHash<4>("44114411"); | ||||
| 	out << FixedHash<32>{}; | ||||
| 	out << FixedHash<2>("f77f"); | ||||
| 	out << FixedHash<1>("1"); | ||||
| 	BOOST_CHECK_EQUAL(out.str(), "441144110000000000000000000000000000000000000000000000000000000000000000f77f01"); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user