mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Right-aligns hex numbers and introduces alignment built-ins.
This commit is contained in:
parent
eb5bde95b3
commit
a40fbf0fc4
@ -75,12 +75,12 @@ bool SemanticTest::run(ostream& _stream, string const& _linePrefix, bool const _
|
||||
AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl;
|
||||
for (auto const& test: m_tests)
|
||||
_stream << test.format(_linePrefix, false, _formatted) << endl;
|
||||
|
||||
_stream << endl;
|
||||
AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl;
|
||||
for (auto const& test: m_tests)
|
||||
_stream << test.format(_linePrefix, true, _formatted) << endl;
|
||||
|
||||
AnsiColorized(_stream, _formatted, {BOLD, RED}) << _linePrefix
|
||||
AnsiColorized(_stream, _formatted, {BOLD, RED}) << _linePrefix << endl << _linePrefix
|
||||
<< "Attention: Updates on the test will apply the detected format displayed." << endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
contract C {
|
||||
function f() public returns (uint) {
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
function g(uint x, uint y) public returns (uint) {
|
||||
return x - y;
|
||||
@ -8,18 +8,20 @@ contract C {
|
||||
function h() public payable returns (uint) {
|
||||
return f();
|
||||
}
|
||||
function x(bytes32 b) public returns (bytes32) {
|
||||
function i(bytes32 b) public returns (bytes32) {
|
||||
return b;
|
||||
}
|
||||
function t(bool b) public returns (bool) {
|
||||
function j(bool b) public returns (bool) {
|
||||
return !b;
|
||||
}
|
||||
function k(bytes32 b) public returns (bytes32) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> 1
|
||||
// f() -> 2
|
||||
// g(uint256,uint256): 1, -2 -> 3
|
||||
// h(), 1 ether -> 1
|
||||
// j() -> FAILURE
|
||||
// i() # Does not exist. # -> FAILURE # Reverts. #
|
||||
// x(bytes32): 0x31 -> 0x31
|
||||
// t(bool): true -> false
|
||||
// h(), 1 ether -> 2
|
||||
// i() -> FAILURE
|
||||
// j(bool): true -> false
|
||||
// k(bytes32): 0x31 -> 0x31
|
||||
|
28
test/libsolidity/semanticTests/smoke_test_alignment.sol
Normal file
28
test/libsolidity/semanticTests/smoke_test_alignment.sol
Normal file
@ -0,0 +1,28 @@
|
||||
contract C {
|
||||
uint256 public stateDecimal = 0x20;
|
||||
}
|
||||
|
||||
contract D {
|
||||
bool public stateBool = true;
|
||||
uint256 public stateDecimal = 42;
|
||||
bytes32 public stateBytes = "\x42\x00\xef";
|
||||
|
||||
function internalStateDecimal() public returns (uint256) {
|
||||
return (new C()).stateDecimal();
|
||||
}
|
||||
|
||||
function update(bool _bool, uint256 _decimal, bytes32 _bytes) public returns (bool, uint256, bytes32) {
|
||||
stateBool = _bool;
|
||||
stateDecimal = _decimal;
|
||||
stateBytes = _bytes;
|
||||
return (stateBool, stateDecimal, stateBytes);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// stateBool() -> true
|
||||
// stateBool() -> right(true)
|
||||
// stateDecimal() -> 42
|
||||
// stateDecimal() -> right(42)
|
||||
// stateBytes() -> left(0x4200ef)
|
||||
// internalStateDecimal() -> 0x20
|
||||
// update(bool,uint256,bytes32): false, -23, left(0x2300ef) -> false, -23, left(0x2300ef)
|
@ -33,6 +33,45 @@ using namespace dev::solidity::test;
|
||||
using namespace std;
|
||||
using namespace soltest;
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class DeclaredAlignment
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
None,
|
||||
};
|
||||
|
||||
inline bytes alignLeft(bytes _bytes)
|
||||
{
|
||||
return std::move(_bytes) + bytes(32 - _bytes.size(), 0);
|
||||
}
|
||||
|
||||
inline bytes alignRight(bytes _bytes)
|
||||
{
|
||||
return bytes(32 - _bytes.size(), 0) + std::move(_bytes);
|
||||
}
|
||||
|
||||
inline bytes applyAlign(DeclaredAlignment _alignment, ABIType& _abiType, bytes _converted)
|
||||
{
|
||||
if (_alignment != DeclaredAlignment::None)
|
||||
_abiType.alignDeclared = true;
|
||||
|
||||
switch (_alignment)
|
||||
{
|
||||
case DeclaredAlignment::Left:
|
||||
_abiType.align = ABIType::AlignLeft;
|
||||
return alignLeft(std::move(_converted));
|
||||
case DeclaredAlignment::Right:
|
||||
_abiType.align = ABIType::AlignRight;
|
||||
return alignRight(std::move(_converted));
|
||||
default:
|
||||
_abiType.align = ABIType::AlignRight;
|
||||
return alignRight(std::move(_converted));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<dev::solidity::test::FunctionCall> TestFileParser::parseFunctionCalls()
|
||||
{
|
||||
vector<FunctionCall> calls;
|
||||
@ -137,9 +176,16 @@ string TestFileParser::parseFunctionSignature()
|
||||
|
||||
u256 TestFileParser::parseFunctionCallValue()
|
||||
{
|
||||
u256 value = convertNumber(parseDecimalNumber());
|
||||
try
|
||||
{
|
||||
u256 value{parseDecimalNumber()};
|
||||
expect(Token::Ether);
|
||||
return value;
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
throw Error(Error::Type::ParserError, "Ether value encoding invalid.");
|
||||
}
|
||||
}
|
||||
|
||||
FunctionCallArgs TestFileParser::parseFunctionCallArguments()
|
||||
@ -192,51 +238,75 @@ Parameter TestFileParser::parseParameter()
|
||||
|
||||
tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
|
||||
{
|
||||
ABIType abiType{ABIType::None, ABIType::AlignNone, 0};
|
||||
DeclaredAlignment alignment{DeclaredAlignment::None};
|
||||
bytes result{toBigEndian(u256{0})};
|
||||
string rawString;
|
||||
bool isSigned = false;
|
||||
|
||||
if (accept(Token::Left, true))
|
||||
{
|
||||
rawString += formatToken(Token::Left);
|
||||
expect(Token::LParen);
|
||||
rawString += formatToken(Token::LParen);
|
||||
alignment = DeclaredAlignment::Left;
|
||||
}
|
||||
if (accept(Token::Right, true))
|
||||
{
|
||||
rawString += formatToken(Token::Right);
|
||||
expect(Token::LParen);
|
||||
rawString += formatToken(Token::LParen);
|
||||
alignment = DeclaredAlignment::Right;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
u256 number{0};
|
||||
ABIType abiType{ABIType::None, ABIType::AlignRight, 0};
|
||||
string rawString;
|
||||
|
||||
if (accept(Token::Sub))
|
||||
if (accept(Token::Sub, true))
|
||||
{
|
||||
abiType = ABIType{ABIType::SignedDec, ABIType::AlignRight, 32};
|
||||
expect(Token::Sub);
|
||||
rawString += formatToken(Token::Sub);
|
||||
string parsed = parseDecimalNumber();
|
||||
rawString += parsed;
|
||||
number = convertNumber(parsed) * -1;
|
||||
isSigned = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (accept(Token::Boolean))
|
||||
{
|
||||
if (isSigned)
|
||||
throw Error(Error::Type::ParserError, "Invalid boolean literal.");
|
||||
abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32};
|
||||
string parsed = parseBoolean();
|
||||
rawString += parsed;
|
||||
return make_tuple(toBigEndian(u256{convertBoolean(parsed)}), abiType, rawString);
|
||||
result = applyAlign(alignment, abiType, convertBoolean(parsed));
|
||||
}
|
||||
else if (accept(Token::HexNumber))
|
||||
{
|
||||
abiType = ABIType{ABIType::Hex, ABIType::AlignLeft, 32};
|
||||
if (isSigned)
|
||||
throw Error(Error::Type::ParserError, "Invalid hex number literal.");
|
||||
abiType = ABIType{ABIType::Hex, ABIType::AlignRight, 32};
|
||||
string parsed = parseHexNumber();
|
||||
rawString += parsed;
|
||||
return make_tuple(convertHexNumber(parsed), abiType, rawString);
|
||||
result = applyAlign(alignment, abiType, convertHexNumber(parsed));
|
||||
}
|
||||
else if (accept(Token::Number))
|
||||
{
|
||||
abiType = ABIType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec;
|
||||
abiType = ABIType{type, ABIType::AlignRight, 32};
|
||||
string parsed = parseDecimalNumber();
|
||||
rawString += parsed;
|
||||
number = convertNumber(parsed);
|
||||
if (isSigned)
|
||||
parsed = "-" + parsed;
|
||||
result = applyAlign(alignment, abiType, convertNumber(parsed));
|
||||
}
|
||||
else if (accept(Token::Failure, true))
|
||||
{
|
||||
if (isSigned)
|
||||
throw Error(Error::Type::ParserError, "Invalid failure literal.");
|
||||
abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0};
|
||||
return make_tuple(bytes{}, abiType, rawString);
|
||||
result = bytes{};
|
||||
}
|
||||
if (alignment != DeclaredAlignment::None)
|
||||
{
|
||||
expect(Token::RParen);
|
||||
rawString += formatToken(Token::RParen);
|
||||
}
|
||||
return make_tuple(toBigEndian(number), abiType, rawString);
|
||||
return make_tuple(result, abiType, rawString);
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
@ -298,21 +368,21 @@ string TestFileParser::parseHexNumber()
|
||||
return literal;
|
||||
}
|
||||
|
||||
bool TestFileParser::convertBoolean(string const& _literal)
|
||||
bytes TestFileParser::convertBoolean(string const& _literal)
|
||||
{
|
||||
if (_literal == "true")
|
||||
return true;
|
||||
return bytes{true};
|
||||
else if (_literal == "false")
|
||||
return false;
|
||||
return bytes{false};
|
||||
else
|
||||
throw Error(Error::Type::ParserError, "Boolean literal invalid.");
|
||||
}
|
||||
|
||||
u256 TestFileParser::convertNumber(string const& _literal)
|
||||
bytes TestFileParser::convertNumber(string const& _literal)
|
||||
{
|
||||
try
|
||||
{
|
||||
return u256{_literal};
|
||||
return toCompactBigEndian(u256{_literal});
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
@ -330,8 +400,7 @@ bytes TestFileParser::convertHexNumber(string const& _literal)
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes result = fromHex(_literal);
|
||||
return result + bytes(32 - result.size(), 0);
|
||||
return fromHex(_literal);
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
@ -357,6 +426,8 @@ void TestFileParser::Scanner::scanNextToken()
|
||||
if (_literal == "true") return TokenDesc{Token::Boolean, _literal};
|
||||
if (_literal == "false") return TokenDesc{Token::Boolean, _literal};
|
||||
if (_literal == "ether") return TokenDesc{Token::Ether, _literal};
|
||||
if (_literal == "left") return TokenDesc{Token::Left, _literal};
|
||||
if (_literal == "right") return TokenDesc{Token::Right, _literal};
|
||||
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
|
||||
return TokenDesc{Token::Identifier, _literal};
|
||||
};
|
||||
|
@ -62,6 +62,8 @@ namespace test
|
||||
K(Ether, "ether", 0) \
|
||||
K(Boolean, "boolean", 0) \
|
||||
/* special keywords */ \
|
||||
K(Left, "left", 0) \
|
||||
K(Right, "right", 0) \
|
||||
K(Failure, "FAILURE", 0) \
|
||||
|
||||
namespace soltest
|
||||
@ -112,12 +114,13 @@ struct ABIType
|
||||
enum Align
|
||||
{
|
||||
AlignLeft,
|
||||
AlignRight
|
||||
AlignRight,
|
||||
AlignNone,
|
||||
};
|
||||
|
||||
Type type = ABIType::None;
|
||||
Align align = ABIType::AlignRight;
|
||||
size_t size = 0;
|
||||
bool alignDeclared = false;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -370,16 +373,15 @@ private:
|
||||
/// Parses the current hex number literal.
|
||||
std::string parseHexNumber();
|
||||
|
||||
/// Coverts "true" to `true`, "false" to `false` and throws
|
||||
/// otherwise.
|
||||
bool convertBoolean(std::string const& _literal);
|
||||
/// Tries to convert \param _literal to an unpadded `bytes`
|
||||
/// representation of the boolean number literal. Throws if conversion fails.
|
||||
bytes convertBoolean(std::string const& _literal);
|
||||
|
||||
/// Tries to convert \param _literal to right-aligned, padded `u256`
|
||||
/// representation of the decimal number literal.
|
||||
/// Throws if conversion fails.
|
||||
u256 convertNumber(std::string const& _literal);
|
||||
/// Tries to convert \param _literal to an unpadded `bytes`
|
||||
/// representation of the decimal number literal. Throws if conversion fails.
|
||||
bytes convertNumber(std::string const& _literal);
|
||||
|
||||
/// Tries to convert \param _literal to left-aligned, padded `bytes`
|
||||
/// Tries to convert \param _literal to an unpadded `bytes`
|
||||
/// representation of the hex literal. Throws if conversion fails.
|
||||
bytes convertHexNumber(std::string const& _literal);
|
||||
|
||||
|
@ -336,8 +336,8 @@ BOOST_AUTO_TEST_CASE(call_arguments_left_aligned)
|
||||
"f(bytes32,bytes32)",
|
||||
false,
|
||||
fmt::encodeArgs(
|
||||
u256("0x6161000000000000000000000000000000000000000000000000000000000000"),
|
||||
u256("0x420000EF00000000000000000000000000000000000000000000000000000000")
|
||||
fromHex("0x6161"),
|
||||
fromHex("0x420000EF")
|
||||
),
|
||||
fmt::encodeArgs(1)
|
||||
);
|
||||
@ -347,8 +347,8 @@ BOOST_AUTO_TEST_CASE(call_arguments_left_aligned)
|
||||
"g(bytes32,bytes32)",
|
||||
false,
|
||||
fmt::encodeArgs(
|
||||
u256("0x0616000000000000000000000000000000000000000000000000000000000000"),
|
||||
u256("0x0042EF0000000000000000000000000000000000000000000000000000000000")
|
||||
fromHex("0x0616"),
|
||||
fromHex("0x0042EF00")
|
||||
),
|
||||
fmt::encodeArgs(1)
|
||||
);
|
||||
@ -493,6 +493,46 @@ BOOST_AUTO_TEST_CASE(call_raw_arguments)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_builtin_left_decimal)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f(): left(1), left(0x20) -> left(-2), left(true)
|
||||
)";
|
||||
auto const calls = parse(source);
|
||||
BOOST_REQUIRE_EQUAL(calls.size(), 1);
|
||||
testFunctionCall(
|
||||
calls.at(0),
|
||||
Mode::SingleLine,
|
||||
"f()",
|
||||
false,
|
||||
fmt::encodeArgs(
|
||||
fmt::encode(toCompactBigEndian(u256{1}), false),
|
||||
fmt::encode(fromHex("0x20"), false)
|
||||
),
|
||||
fmt::encodeArgs(
|
||||
fmt::encode(toCompactBigEndian(u256{-2}), false),
|
||||
fmt::encode(bytes{true}, false)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_builtin_right_decimal)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f(): right(1), right(0x20) -> right(-2), right(true)
|
||||
)";
|
||||
auto const calls = parse(source);
|
||||
BOOST_REQUIRE_EQUAL(calls.size(), 1);
|
||||
testFunctionCall(
|
||||
calls.at(0),
|
||||
Mode::SingleLine,
|
||||
"f()",
|
||||
false,
|
||||
fmt::encodeArgs(1, fromHex("0x20")),
|
||||
fmt::encodeArgs(-2, true)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_newline_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
@ -603,6 +643,30 @@ BOOST_AUTO_TEST_CASE(call_hex_number_invalid)
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_signed_bool_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f() -> -true
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_signed_failure_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f() -> -FAILURE
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_signed_hex_number_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f() -> -0x42
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_colon)
|
||||
{
|
||||
char const* source = R"(
|
||||
|
@ -48,7 +48,11 @@ string TestFunctionCall::format(string const& _linePrefix, bool const _renderRes
|
||||
if (!m_call.arguments.rawBytes().empty())
|
||||
{
|
||||
string output = formatRawParameters(m_call.arguments.parameters, _linePrefix);
|
||||
_stream << colon << output;
|
||||
_stream << colon;
|
||||
if (_singleLine)
|
||||
_stream << ws;
|
||||
_stream << output;
|
||||
|
||||
}
|
||||
|
||||
/// Formats comments on the function parameters and the arrow taking
|
||||
@ -76,13 +80,19 @@ string TestFunctionCall::format(string const& _linePrefix, bool const _renderRes
|
||||
{
|
||||
bytes output = m_call.expectations.rawBytes();
|
||||
bool const isFailure = m_call.expectations.failure;
|
||||
result = isFailure ? failure : formatBytesParameters(output, m_call.expectations.result);
|
||||
result = isFailure ?
|
||||
failure :
|
||||
formatRawParameters(m_call.expectations.result);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes output = m_rawBytes;
|
||||
bool const isFailure = m_failure;
|
||||
result = isFailure ? failure : formatBytesParameters(output, m_call.expectations.result);
|
||||
result = isFailure ?
|
||||
failure :
|
||||
matchesExpectation() ?
|
||||
formatRawParameters(m_call.expectations.result) :
|
||||
formatBytesParameters(output, m_call.expectations.result);
|
||||
}
|
||||
AnsiColorized(_stream, highlight, {dev::formatting::RED_BACKGROUND}) << result;
|
||||
|
||||
@ -106,8 +116,6 @@ string TestFunctionCall::format(string const& _linePrefix, bool const _renderRes
|
||||
formatOutput(true);
|
||||
else
|
||||
formatOutput(false);
|
||||
// _stream << endl;
|
||||
|
||||
return _stream.str();
|
||||
}
|
||||
|
||||
@ -131,14 +139,12 @@ string TestFunctionCall::formatBytesParameters(bytes const& _bytes, dev::solidit
|
||||
// be signed. If an unsigned was detected in the expectations,
|
||||
// but the actual result returned a signed, it would be formatted
|
||||
// incorrectly.
|
||||
soltestAssert(param.abiType.align == ABIType::AlignRight, "Unsigned decimals must be right-aligned.");
|
||||
if (*byteRange.begin() & 0x80)
|
||||
resultStream << u2s(fromBigEndian<u256>(byteRange));
|
||||
else
|
||||
resultStream << fromBigEndian<u256>(byteRange);
|
||||
break;
|
||||
case ABIType::SignedDec:
|
||||
soltestAssert(param.abiType.align == ABIType::AlignRight, "Signed decimals must be right-aligned.");
|
||||
if (*byteRange.begin() & 0x80)
|
||||
resultStream << u2s(fromBigEndian<u256>(byteRange));
|
||||
else
|
||||
@ -146,19 +152,16 @@ string TestFunctionCall::formatBytesParameters(bytes const& _bytes, dev::solidit
|
||||
break;
|
||||
case ABIType::Boolean:
|
||||
{
|
||||
soltestAssert(param.abiType.align == ABIType::AlignRight, "Booleans must be right-aligned.");
|
||||
u256 result = fromBigEndian<u256>(byteRange);
|
||||
if (result == 0)
|
||||
resultStream << "false";
|
||||
else
|
||||
else if (result == 1)
|
||||
resultStream << "true";
|
||||
else
|
||||
resultStream << result;
|
||||
break;
|
||||
}
|
||||
case ABIType::Hex:
|
||||
soltestAssert(param.abiType.align == ABIType::AlignLeft, "Hex numbers must be left-aligned.");
|
||||
byteRange.erase(
|
||||
std::remove(byteRange.begin(), byteRange.end(), 0), byteRange.end()
|
||||
);
|
||||
resultStream << toHex(byteRange, HexPrefix::Add);
|
||||
break;
|
||||
case ABIType::Failure:
|
||||
@ -180,10 +183,10 @@ string TestFunctionCall::formatRawParameters(dev::solidity::test::ParameterList
|
||||
for (auto const& param: _params)
|
||||
{
|
||||
if (param.format.newline)
|
||||
resultStream << endl << _linePrefix << "//";
|
||||
resultStream << " " << param.rawString;
|
||||
resultStream << endl << _linePrefix << "// ";
|
||||
resultStream << param.rawString;
|
||||
if (¶m != &_params.back())
|
||||
resultStream << ",";
|
||||
resultStream << ", ";
|
||||
}
|
||||
return resultStream.str();
|
||||
}
|
||||
|
@ -47,6 +47,43 @@ BOOST_AUTO_TEST_CASE(format_unsigned_singleline)
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8): 1 -> 1");
|
||||
|
||||
test.setRawBytes(toBigEndian(u256{2}));
|
||||
test.setFailure(false);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format("", true), "// f(uint8): 1 -> 2");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_unsigned_singleline_signed_encoding)
|
||||
{
|
||||
bytes expectedBytes = toBigEndian(u256{1});
|
||||
ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
Parameter param{expectedBytes, "1", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{param}, false, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{param}, string{}};
|
||||
FunctionCall call{"f(uint8)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8): 1 -> 1");
|
||||
|
||||
test.setRawBytes(toBigEndian(u256{-1}));
|
||||
test.setFailure(false);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format("", true), "// f(uint8): 1 -> -1");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_unsigned_multiline)
|
||||
{
|
||||
bytes expectedBytes = toBigEndian(u256{1});
|
||||
ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
Parameter result{expectedBytes, "1", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{result}, false, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{}, string{}};
|
||||
FunctionCall call{"f(uint8)", 0, arguments, expectations};
|
||||
call.displayMode = FunctionCall::DisplayMode::MultiLine;
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8)\n// -> 1");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_multiple_unsigned_singleline)
|
||||
@ -73,23 +110,14 @@ BOOST_AUTO_TEST_CASE(format_signed_singleline)
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(int8): -1 -> -1");
|
||||
|
||||
test.setRawBytes(toBigEndian(u256{-2}));
|
||||
test.setFailure(false);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format("", true), "// f(int8): -1 -> -2");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_hex_singleline)
|
||||
{
|
||||
bytes result = fromHex("0x31");
|
||||
bytes expectedBytes = result + bytes(32 - result.size(), 0);
|
||||
ABIType abiType{ABIType::Hex, ABIType::AlignLeft, 32};
|
||||
Parameter param{expectedBytes, "0x31", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{param}, false, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{param}, string{}};
|
||||
FunctionCall call{"f(bytes32)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(bytes32): 0x31 -> 0x31");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_hex_right_align)
|
||||
{
|
||||
bytes result = fromHex("0x31");
|
||||
bytes expectedBytes = result + bytes(32 - result.size(), 0);
|
||||
@ -100,7 +128,14 @@ BOOST_AUTO_TEST_CASE(format_hex_right_align)
|
||||
FunctionCall call{"f(bytes32)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_THROW(test.format(), runtime_error);
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(bytes32): 0x31 -> 0x31");
|
||||
|
||||
bytes actualResult = fromHex("0x32");
|
||||
bytes actualBytes = actualResult + bytes(32 - actualResult.size(), 0);
|
||||
test.setRawBytes(actualBytes);
|
||||
test.setFailure(false);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format("", true), "// f(bytes32): 0x31 -> 0x3200000000000000000000000000000000000000000000000000000000000000");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_bool_true_singleline)
|
||||
@ -114,6 +149,13 @@ BOOST_AUTO_TEST_CASE(format_bool_true_singleline)
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(bool): true -> true");
|
||||
|
||||
bytes actualResult = bytes{false};
|
||||
bytes actualBytes = actualResult + bytes(32 - actualResult.size(), 0);
|
||||
test.setRawBytes(actualBytes);
|
||||
test.setFailure(false);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format("", true), "// f(bool): true -> false");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_bool_false_singleline)
|
||||
@ -129,48 +171,79 @@ BOOST_AUTO_TEST_CASE(format_bool_false_singleline)
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(bool): false -> false");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_bool_left_align_singleline)
|
||||
BOOST_AUTO_TEST_CASE(format_bool_left_singleline)
|
||||
{
|
||||
bytes expectedBytes = toBigEndian(u256{true});
|
||||
bytes expectedBytes = toBigEndian(u256{false});
|
||||
ABIType abiType{ABIType::Boolean, ABIType::AlignLeft, 32};
|
||||
Parameter param{expectedBytes, "true", abiType, FormatInfo{}};
|
||||
Parameter param{expectedBytes, "left(false)", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{param}, false, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{param}, string{}};
|
||||
FunctionCall call{"f(bool)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_THROW(test.format(), runtime_error);
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(bool): left(false) -> left(false)");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_hex_number_right_singleline)
|
||||
{
|
||||
bytes result = fromHex("0x42");
|
||||
bytes expectedBytes = result + bytes(32 - result.size(), 0);
|
||||
ABIType abiType{ABIType::Hex, ABIType::AlignRight, 32};
|
||||
Parameter param{expectedBytes, "right(0x42)", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{param}, false, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{param}, string{}};
|
||||
FunctionCall call{"f(bool)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(bool): right(0x42) -> right(0x42)");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_empty_byte_range)
|
||||
{
|
||||
bytes expectedBytes;
|
||||
ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
ABIType abiType{ABIType::None, ABIType::AlignNone, 0};
|
||||
Parameter param{expectedBytes, "1", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{param}, false, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{}, string{}};
|
||||
FunctionCall call{"f()", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f() -> ");
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f() -> 1");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_failure_singleline)
|
||||
{
|
||||
bytes expectedBytes = toBigEndian(u256{1});
|
||||
ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
Parameter param{expectedBytes, "1", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{}, true, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{param}, string{}};
|
||||
FunctionCall call{"f(uint8)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_EQUAL(test.format(), "// f(uint8): 1 -> FAILURE");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_parameter_encoding_too_short)
|
||||
{
|
||||
bytes expectedBytes = toBigEndian(u256{1}) + toBigEndian(u256{1});
|
||||
ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 20};
|
||||
Parameter param{expectedBytes, "1", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{param, param}, false, string{}};
|
||||
FunctionCallArgs arguments{vector<Parameter>{param, param}, string{}};
|
||||
FunctionCall call{"f(uint8, uint8)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_THROW(test.format(), runtime_error);
|
||||
bytes resultBytes = toBigEndian(u256{1}) + toBigEndian(u256{2});
|
||||
test.setRawBytes(resultBytes);
|
||||
test.setFailure(false);
|
||||
|
||||
BOOST_REQUIRE_THROW(test.format("", true), runtime_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format_byte_range_too_short)
|
||||
{
|
||||
bytes expectedBytes{0};
|
||||
bytes expectedBytes = toBigEndian(u256{1});
|
||||
ABIType abiType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
Parameter param{expectedBytes, "1", abiType, FormatInfo{}};
|
||||
FunctionCallExpectations expectations{vector<Parameter>{param, param}, false, string{}};
|
||||
@ -178,7 +251,11 @@ BOOST_AUTO_TEST_CASE(format_byte_range_too_short)
|
||||
FunctionCall call{"f(uint8, uint8)", 0, arguments, expectations};
|
||||
TestFunctionCall test{call};
|
||||
|
||||
BOOST_REQUIRE_THROW(test.format(), runtime_error);
|
||||
bytes resultBytes{0};
|
||||
test.setRawBytes(resultBytes);
|
||||
test.setFailure(false);
|
||||
|
||||
BOOST_REQUIRE_THROW(test.format("", true), runtime_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user