Skip to content

[soltest] Add support for boolean literals #6072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Bugfixes:

Build System:
* Soltest: Add support for left-aligned, padded hex literals.
* Soltest: Add support for right-aligned, padded boolean literals.

### 0.5.4 (2019-02-12)

Expand Down
4 changes: 4 additions & 0 deletions test/libsolidity/semanticTests/smoke_test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ contract C {
function x(bytes32 b) public returns (bytes32) {
return b;
}
function t(bool b) public returns (bool) {
return !b;
}
}
// ----
// f() -> 1
Expand All @@ -19,3 +22,4 @@ contract C {
// j() -> FAILURE
// i() # Does not exist. # -> FAILURE # Reverts. #
// x(bytes32): 0x31 -> 0x31
// t(bool): true -> false
28 changes: 27 additions & 1 deletion test/libsolidity/util/TestFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,14 @@ tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
}
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};
string parsed = parseHexNumber();
Expand Down Expand Up @@ -262,6 +269,13 @@ string TestFileParser::parseIdentifierOrTuple()
return identOrTuple;
}

string TestFileParser::parseBoolean()
{
string literal = m_scanner.currentLiteral();
expect(Token::Boolean);
return literal;
}

string TestFileParser::parseComment()
{
string comment = m_scanner.currentLiteral();
Expand All @@ -284,6 +298,16 @@ string TestFileParser::parseHexNumber()
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)
{
try
Expand Down Expand Up @@ -330,6 +354,8 @@ void TestFileParser::Scanner::scanNextToken()
assert(formatToken(Token::NUM_TOKENS) == "");

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 == "FAILURE") return TokenDesc{Token::Failure, _literal};
return TokenDesc{Token::Identifier, _literal};
Expand Down
9 changes: 9 additions & 0 deletions test/libsolidity/util/TestFileParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace test
T(Identifier, "identifier", 0) \
/* type keywords */ \
K(Ether, "ether", 0) \
K(Boolean, "boolean", 0) \
/* special keywords */ \
K(Failure, "FAILURE", 0) \

Expand Down Expand Up @@ -103,6 +104,7 @@ struct ABIType
{
UnsignedDec,
SignedDec,
Boolean,
Hex,
Failure,
None
Expand Down Expand Up @@ -355,6 +357,9 @@ class TestFileParser
/// and / or parentheses like `((uint, uint), (uint, (uint, uint)), uint)`.
std::string parseIdentifierOrTuple();

/// Parses a boolean literal.
std::string parseBoolean();

/// Parses a comment that is defined like this:
/// # A nice comment. #
std::string parseComment();
Expand All @@ -365,6 +370,10 @@ class TestFileParser
/// 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 right-aligned, padded `u256`
/// representation of the decimal number literal.
/// Throws if conversion fails.
Expand Down
17 changes: 17 additions & 0 deletions test/libsolidity/util/TestFileParserTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
char const* source = R"(
Expand Down
24 changes: 17 additions & 7 deletions test/libsolidity/util/TestFunctionCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,6 @@ string TestFunctionCall::formatBytesParameters(bytes const& _bytes, ParameterLis
bytes byteRange{it, offsetIter};
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:
// Check if the detected type was wrong and if this could
// be signed. If an unsigned was detected in the expectations,
Expand All @@ -144,6 +137,23 @@ string TestFunctionCall::formatBytesParameters(bytes const& _bytes, ParameterLis
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
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:
soltestAssert(param.abiType.align == ABIType::AlignLeft, "Hex numbers must be left-aligned.");
byteRange.erase(
Expand Down
39 changes: 39 additions & 0 deletions test/libsolidity/util/TestFunctionCallTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,45 @@ BOOST_AUTO_TEST_CASE(format_hex_right_align)
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)
{
bytes expectedBytes;
Expand Down