mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6072 from ethereum/soltest-bool-literals
[soltest] Add support for boolean literals
This commit is contained in:
commit
dd97a9418a
@ -23,6 +23,7 @@ Bugfixes:
|
|||||||
|
|
||||||
Build System:
|
Build System:
|
||||||
* Soltest: Add support for left-aligned, padded hex literals.
|
* Soltest: Add support for left-aligned, padded hex literals.
|
||||||
|
* Soltest: Add support for right-aligned, padded boolean literals.
|
||||||
|
|
||||||
### 0.5.4 (2019-02-12)
|
### 0.5.4 (2019-02-12)
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ contract C {
|
|||||||
function x(bytes32 b) public returns (bytes32) {
|
function x(bytes32 b) public returns (bytes32) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
function t(bool b) public returns (bool) {
|
||||||
|
return !b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// f() -> 1
|
// f() -> 1
|
||||||
@ -19,3 +22,4 @@ contract C {
|
|||||||
// j() -> FAILURE
|
// j() -> FAILURE
|
||||||
// i() # Does not exist. # -> FAILURE # Reverts. #
|
// i() # Does not exist. # -> FAILURE # Reverts. #
|
||||||
// x(bytes32): 0x31 -> 0x31
|
// x(bytes32): 0x31 -> 0x31
|
||||||
|
// t(bool): true -> false
|
||||||
|
@ -209,7 +209,14 @@ tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (accept(Token::HexNumber))
|
if (accept(Token::Boolean))
|
||||||
|
{
|
||||||
|
abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32};
|
||||||
|
string parsed = parseBoolean();
|
||||||
|
rawString += parsed;
|
||||||
|
return make_tuple(toBigEndian(u256{convertBoolean(parsed)}), abiType, rawString);
|
||||||
|
}
|
||||||
|
else if (accept(Token::HexNumber))
|
||||||
{
|
{
|
||||||
abiType = ABIType{ABIType::Hex, ABIType::AlignLeft, 32};
|
abiType = ABIType{ABIType::Hex, ABIType::AlignLeft, 32};
|
||||||
string parsed = parseHexNumber();
|
string parsed = parseHexNumber();
|
||||||
@ -262,6 +269,13 @@ string TestFileParser::parseIdentifierOrTuple()
|
|||||||
return identOrTuple;
|
return identOrTuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string TestFileParser::parseBoolean()
|
||||||
|
{
|
||||||
|
string literal = m_scanner.currentLiteral();
|
||||||
|
expect(Token::Boolean);
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
string TestFileParser::parseComment()
|
string TestFileParser::parseComment()
|
||||||
{
|
{
|
||||||
string comment = m_scanner.currentLiteral();
|
string comment = m_scanner.currentLiteral();
|
||||||
@ -284,6 +298,16 @@ string TestFileParser::parseHexNumber()
|
|||||||
return literal;
|
return literal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TestFileParser::convertBoolean(string const& _literal)
|
||||||
|
{
|
||||||
|
if (_literal == "true")
|
||||||
|
return true;
|
||||||
|
else if (_literal == "false")
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
throw Error(Error::Type::ParserError, "Boolean literal invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
u256 TestFileParser::convertNumber(string const& _literal)
|
u256 TestFileParser::convertNumber(string const& _literal)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -330,6 +354,8 @@ void TestFileParser::Scanner::scanNextToken()
|
|||||||
assert(formatToken(Token::NUM_TOKENS) == "");
|
assert(formatToken(Token::NUM_TOKENS) == "");
|
||||||
|
|
||||||
auto detectKeyword = [](std::string const& _literal = "") -> TokenDesc {
|
auto detectKeyword = [](std::string const& _literal = "") -> TokenDesc {
|
||||||
|
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 == "ether") return TokenDesc{Token::Ether, _literal};
|
||||||
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
|
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
|
||||||
return TokenDesc{Token::Identifier, _literal};
|
return TokenDesc{Token::Identifier, _literal};
|
||||||
|
@ -60,6 +60,7 @@ namespace test
|
|||||||
T(Identifier, "identifier", 0) \
|
T(Identifier, "identifier", 0) \
|
||||||
/* type keywords */ \
|
/* type keywords */ \
|
||||||
K(Ether, "ether", 0) \
|
K(Ether, "ether", 0) \
|
||||||
|
K(Boolean, "boolean", 0) \
|
||||||
/* special keywords */ \
|
/* special keywords */ \
|
||||||
K(Failure, "FAILURE", 0) \
|
K(Failure, "FAILURE", 0) \
|
||||||
|
|
||||||
@ -103,6 +104,7 @@ struct ABIType
|
|||||||
{
|
{
|
||||||
UnsignedDec,
|
UnsignedDec,
|
||||||
SignedDec,
|
SignedDec,
|
||||||
|
Boolean,
|
||||||
Hex,
|
Hex,
|
||||||
Failure,
|
Failure,
|
||||||
None
|
None
|
||||||
@ -355,6 +357,9 @@ private:
|
|||||||
/// and / or parentheses like `((uint, uint), (uint, (uint, uint)), uint)`.
|
/// and / or parentheses like `((uint, uint), (uint, (uint, uint)), uint)`.
|
||||||
std::string parseIdentifierOrTuple();
|
std::string parseIdentifierOrTuple();
|
||||||
|
|
||||||
|
/// Parses a boolean literal.
|
||||||
|
std::string parseBoolean();
|
||||||
|
|
||||||
/// Parses a comment that is defined like this:
|
/// Parses a comment that is defined like this:
|
||||||
/// # A nice comment. #
|
/// # A nice comment. #
|
||||||
std::string parseComment();
|
std::string parseComment();
|
||||||
@ -365,6 +370,10 @@ private:
|
|||||||
/// Parses the current hex number literal.
|
/// Parses the current hex number literal.
|
||||||
std::string parseHexNumber();
|
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 right-aligned, padded `u256`
|
/// Tries to convert \param _literal to right-aligned, padded `u256`
|
||||||
/// representation of the decimal number literal.
|
/// representation of the decimal number literal.
|
||||||
/// Throws if conversion fails.
|
/// Throws if conversion fails.
|
||||||
|
@ -293,6 +293,23 @@ BOOST_AUTO_TEST_CASE(call_arguments)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(call_arguments_bool)
|
||||||
|
{
|
||||||
|
char const* source = R"(
|
||||||
|
// f(bool): true -> false
|
||||||
|
)";
|
||||||
|
auto const calls = parse(source);
|
||||||
|
BOOST_REQUIRE_EQUAL(calls.size(), 1);
|
||||||
|
testFunctionCall(
|
||||||
|
calls.at(0),
|
||||||
|
Mode::SingleLine,
|
||||||
|
"f(bool)",
|
||||||
|
false,
|
||||||
|
fmt::encodeArgs(true),
|
||||||
|
fmt::encodeArgs(false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(call_arguments_tuple)
|
BOOST_AUTO_TEST_CASE(call_arguments_tuple)
|
||||||
{
|
{
|
||||||
char const* source = R"(
|
char const* source = R"(
|
||||||
|
@ -126,13 +126,6 @@ string TestFunctionCall::formatBytesParameters(bytes const& _bytes, ParameterLis
|
|||||||
bytes byteRange{it, offsetIter};
|
bytes byteRange{it, offsetIter};
|
||||||
switch (param.abiType.type)
|
switch (param.abiType.type)
|
||||||
{
|
{
|
||||||
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
|
|
||||||
resultStream << fromBigEndian<u256>(byteRange);
|
|
||||||
break;
|
|
||||||
case ABIType::UnsignedDec:
|
case ABIType::UnsignedDec:
|
||||||
// Check if the detected type was wrong and if this could
|
// Check if the detected type was wrong and if this could
|
||||||
// be signed. If an unsigned was detected in the expectations,
|
// be signed. If an unsigned was detected in the expectations,
|
||||||
@ -144,6 +137,23 @@ string TestFunctionCall::formatBytesParameters(bytes const& _bytes, ParameterLis
|
|||||||
else
|
else
|
||||||
resultStream << fromBigEndian<u256>(byteRange);
|
resultStream << fromBigEndian<u256>(byteRange);
|
||||||
break;
|
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
|
||||||
|
resultStream << fromBigEndian<u256>(byteRange);
|
||||||
|
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
|
||||||
|
resultStream << "true";
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ABIType::Hex:
|
case ABIType::Hex:
|
||||||
soltestAssert(param.abiType.align == ABIType::AlignLeft, "Hex numbers must be left-aligned.");
|
soltestAssert(param.abiType.align == ABIType::AlignLeft, "Hex numbers must be left-aligned.");
|
||||||
byteRange.erase(
|
byteRange.erase(
|
||||||
|
@ -103,6 +103,45 @@ BOOST_AUTO_TEST_CASE(format_hex_right_align)
|
|||||||
BOOST_REQUIRE_THROW(test.format(), runtime_error);
|
BOOST_REQUIRE_THROW(test.format(), runtime_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(format_bool_true_singleline)
|
||||||
|
{
|
||||||
|
bytes expectedBytes = toBigEndian(u256{true});
|
||||||
|
ABIType abiType{ABIType::Boolean, ABIType::AlignRight, 32};
|
||||||
|
Parameter param{expectedBytes, "true", 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): true -> true");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(format_bool_false_singleline)
|
||||||
|
{
|
||||||
|
bytes expectedBytes = toBigEndian(u256{false});
|
||||||
|
ABIType abiType{ABIType::Boolean, ABIType::AlignRight, 32};
|
||||||
|
Parameter param{expectedBytes, "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_EQUAL(test.format(), "// f(bool): false -> false");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(format_bool_left_align_singleline)
|
||||||
|
{
|
||||||
|
bytes expectedBytes = toBigEndian(u256{true});
|
||||||
|
ABIType abiType{ABIType::Boolean, ABIType::AlignLeft, 32};
|
||||||
|
Parameter param{expectedBytes, "true", 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_AUTO_TEST_CASE(format_empty_byte_range)
|
BOOST_AUTO_TEST_CASE(format_empty_byte_range)
|
||||||
{
|
{
|
||||||
bytes expectedBytes;
|
bytes expectedBytes;
|
||||||
|
Loading…
Reference in New Issue
Block a user