mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Adds support for hex string literals in soltest.
This commit is contained in:
parent
2f37cd0986
commit
25ddf85d95
@ -68,6 +68,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 left-aligned, unpadded hex string literals.
|
||||||
* Soltest: Add support for right-aligned, padded boolean literals.
|
* Soltest: Add support for right-aligned, padded boolean literals.
|
||||||
|
|
||||||
### 0.5.4 (2019-02-12)
|
### 0.5.4 (2019-02-12)
|
||||||
|
@ -17,6 +17,9 @@ contract C {
|
|||||||
function k(bytes32 b) public returns (bytes32) {
|
function k(bytes32 b) public returns (bytes32) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
function s() public returns (uint256) {
|
||||||
|
return msg.data.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// f() -> 2
|
// f() -> 2
|
||||||
@ -25,3 +28,4 @@ contract C {
|
|||||||
// i() -> FAILURE
|
// i() -> FAILURE
|
||||||
// j(bool): true -> false
|
// j(bool): true -> false
|
||||||
// k(bytes32): 0x31 -> 0x31
|
// k(bytes32): 0x31 -> 0x31
|
||||||
|
// s(): hex"4200ef" -> 7
|
||||||
|
@ -284,6 +284,17 @@ tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
|
|||||||
rawString += parsed;
|
rawString += parsed;
|
||||||
result = applyAlign(alignment, abiType, convertHexNumber(parsed));
|
result = applyAlign(alignment, abiType, convertHexNumber(parsed));
|
||||||
}
|
}
|
||||||
|
else if (accept(Token::Hex, true))
|
||||||
|
{
|
||||||
|
if (isSigned)
|
||||||
|
throw Error(Error::Type::ParserError, "Invalid hex string literal.");
|
||||||
|
if (alignment != DeclaredAlignment::None)
|
||||||
|
throw Error(Error::Type::ParserError, "Hex string literals cannot be aligned or padded.");
|
||||||
|
string parsed = parseHexNumber();
|
||||||
|
rawString += parsed;
|
||||||
|
result = convertHexString(parsed);
|
||||||
|
abiType = ABIType{ABIType::HexString, ABIType::AlignNone, result.size()};
|
||||||
|
}
|
||||||
else if (accept(Token::Number))
|
else if (accept(Token::Number))
|
||||||
{
|
{
|
||||||
auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec;
|
auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec;
|
||||||
@ -310,7 +321,7 @@ tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
|
|||||||
}
|
}
|
||||||
catch (std::exception const&)
|
catch (std::exception const&)
|
||||||
{
|
{
|
||||||
throw Error(Error::Type::ParserError, "Number encoding invalid.");
|
throw Error(Error::Type::ParserError, "Literal encoding invalid.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,6 +436,21 @@ bytes TestFileParser::convertHexNumber(string const& _literal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bytes TestFileParser::convertHexString(string const& _literal)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_literal.size() % 2)
|
||||||
|
throw Error(Error::Type::ParserError, "Hex string encoding invalid.");
|
||||||
|
else
|
||||||
|
return fromHex(_literal);
|
||||||
|
}
|
||||||
|
catch (std::exception const&)
|
||||||
|
{
|
||||||
|
throw Error(Error::Type::ParserError, "Hex string encoding invalid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TestFileParser::Scanner::readStream(istream& _stream)
|
void TestFileParser::Scanner::readStream(istream& _stream)
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
@ -435,6 +461,8 @@ void TestFileParser::Scanner::readStream(istream& _stream)
|
|||||||
|
|
||||||
void TestFileParser::Scanner::scanNextToken()
|
void TestFileParser::Scanner::scanNextToken()
|
||||||
{
|
{
|
||||||
|
using namespace langutil;
|
||||||
|
|
||||||
// Make code coverage happy.
|
// Make code coverage happy.
|
||||||
assert(formatToken(Token::NUM_TOKENS) == "");
|
assert(formatToken(Token::NUM_TOKENS) == "");
|
||||||
|
|
||||||
@ -444,6 +472,7 @@ void TestFileParser::Scanner::scanNextToken()
|
|||||||
if (_literal == "ether") return TokenDesc{Token::Ether, _literal};
|
if (_literal == "ether") return TokenDesc{Token::Ether, _literal};
|
||||||
if (_literal == "left") return TokenDesc{Token::Left, _literal};
|
if (_literal == "left") return TokenDesc{Token::Left, _literal};
|
||||||
if (_literal == "right") return TokenDesc{Token::Right, _literal};
|
if (_literal == "right") return TokenDesc{Token::Right, _literal};
|
||||||
|
if (_literal == "hex") return TokenDesc{Token::Hex, _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};
|
||||||
};
|
};
|
||||||
@ -495,13 +524,18 @@ void TestFileParser::Scanner::scanNextToken()
|
|||||||
case ']':
|
case ']':
|
||||||
token = selectToken(Token::RBrack);
|
token = selectToken(Token::RBrack);
|
||||||
break;
|
break;
|
||||||
|
case '\"':
|
||||||
|
advance();
|
||||||
|
token = selectToken(Token::HexNumber, scanHexNumber());
|
||||||
|
advance();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (langutil::isIdentifierStart(current()))
|
if (isIdentifierStart(current()))
|
||||||
{
|
{
|
||||||
TokenDesc detectedToken = detectKeyword(scanIdentifierOrKeyword());
|
TokenDesc detectedToken = detectKeyword(scanIdentifierOrKeyword());
|
||||||
token = selectToken(detectedToken.first, detectedToken.second);
|
token = selectToken(detectedToken.first, detectedToken.second);
|
||||||
}
|
}
|
||||||
else if (langutil::isDecimalDigit(current()))
|
else if (isDecimalDigit(current()))
|
||||||
{
|
{
|
||||||
if (current() == '0' && peek() == 'x')
|
if (current() == '0' && peek() == 'x')
|
||||||
{
|
{
|
||||||
@ -512,7 +546,7 @@ void TestFileParser::Scanner::scanNextToken()
|
|||||||
else
|
else
|
||||||
token = selectToken(Token::Number, scanDecimalNumber());
|
token = selectToken(Token::Number, scanDecimalNumber());
|
||||||
}
|
}
|
||||||
else if (langutil::isWhiteSpace(current()))
|
else if (isWhiteSpace(current()))
|
||||||
token = selectToken(Token::Whitespace);
|
token = selectToken(Token::Whitespace);
|
||||||
else if (isEndOfLine())
|
else if (isEndOfLine())
|
||||||
token = selectToken(Token::EOS);
|
token = selectToken(Token::EOS);
|
||||||
|
@ -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(Hex, "hex", 0) \
|
||||||
K(Boolean, "boolean", 0) \
|
K(Boolean, "boolean", 0) \
|
||||||
/* special keywords */ \
|
/* special keywords */ \
|
||||||
K(Left, "left", 0) \
|
K(Left, "left", 0) \
|
||||||
@ -108,6 +109,7 @@ struct ABIType
|
|||||||
SignedDec,
|
SignedDec,
|
||||||
Boolean,
|
Boolean,
|
||||||
Hex,
|
Hex,
|
||||||
|
HexString,
|
||||||
Failure,
|
Failure,
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -385,6 +387,10 @@ private:
|
|||||||
/// representation of the hex literal. Throws if conversion fails.
|
/// representation of the hex literal. Throws if conversion fails.
|
||||||
bytes convertHexNumber(std::string const& _literal);
|
bytes convertHexNumber(std::string const& _literal);
|
||||||
|
|
||||||
|
/// Tries to convert \param _literal to left-aligned, unpadded `bytes`
|
||||||
|
/// representation of the hex string literal. Throws if conversion fails.
|
||||||
|
bytes convertHexString(std::string const& _literal);
|
||||||
|
|
||||||
/// A scanner instance
|
/// A scanner instance
|
||||||
Scanner m_scanner;
|
Scanner m_scanner;
|
||||||
};
|
};
|
||||||
|
@ -310,6 +310,40 @@ BOOST_AUTO_TEST_CASE(call_arguments_bool)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(call_arguments_hex_string)
|
||||||
|
{
|
||||||
|
char const* source = R"(
|
||||||
|
// f(bytes): hex"4200ef" -> hex"ab0023"
|
||||||
|
)";
|
||||||
|
auto const calls = parse(source);
|
||||||
|
BOOST_REQUIRE_EQUAL(calls.size(), 1);
|
||||||
|
testFunctionCall(
|
||||||
|
calls.at(0),
|
||||||
|
Mode::SingleLine,
|
||||||
|
"f(bytes)",
|
||||||
|
false,
|
||||||
|
fromHex("4200ef"),
|
||||||
|
fromHex("ab0023")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(call_arguments_hex_string_lowercase)
|
||||||
|
{
|
||||||
|
char const* source = R"(
|
||||||
|
// f(bytes): hex"4200ef" -> hex"23ef00"
|
||||||
|
)";
|
||||||
|
auto const calls = parse(source);
|
||||||
|
BOOST_REQUIRE_EQUAL(calls.size(), 1);
|
||||||
|
testFunctionCall(
|
||||||
|
calls.at(0),
|
||||||
|
Mode::SingleLine,
|
||||||
|
"f(bytes)",
|
||||||
|
false,
|
||||||
|
fromHex("4200EF"),
|
||||||
|
fromHex("23EF00")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(call_arguments_tuple)
|
BOOST_AUTO_TEST_CASE(call_arguments_tuple)
|
||||||
{
|
{
|
||||||
char const* source = R"(
|
char const* source = R"(
|
||||||
@ -564,6 +598,22 @@ BOOST_AUTO_TEST_CASE(call_builtin_right_decimal)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(call_arguments_hex_string_left_align)
|
||||||
|
{
|
||||||
|
char const* source = R"(
|
||||||
|
// f(bytes): left(hex"4200ef") ->
|
||||||
|
)";
|
||||||
|
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(call_arguments_hex_string_right_align)
|
||||||
|
{
|
||||||
|
char const* source = R"(
|
||||||
|
// f(bytes): right(hex"4200ef") ->
|
||||||
|
)";
|
||||||
|
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(call_newline_invalid)
|
BOOST_AUTO_TEST_CASE(call_newline_invalid)
|
||||||
{
|
{
|
||||||
char const* source = R"(
|
char const* source = R"(
|
||||||
|
@ -164,6 +164,9 @@ string TestFunctionCall::formatBytesParameters(bytes const& _bytes, dev::solidit
|
|||||||
case ABIType::Hex:
|
case ABIType::Hex:
|
||||||
resultStream << toHex(byteRange, HexPrefix::Add);
|
resultStream << toHex(byteRange, HexPrefix::Add);
|
||||||
break;
|
break;
|
||||||
|
case ABIType::HexString:
|
||||||
|
resultStream << "hex\"" << toHex(byteRange) << "\"";
|
||||||
|
break;
|
||||||
case ABIType::Failure:
|
case ABIType::Failure:
|
||||||
break;
|
break;
|
||||||
case ABIType::None:
|
case ABIType::None:
|
||||||
|
@ -138,6 +138,19 @@ BOOST_AUTO_TEST_CASE(format_hex_singleline)
|
|||||||
BOOST_REQUIRE_EQUAL(test.format("", true), "// f(bytes32): 0x31 -> 0x3200000000000000000000000000000000000000000000000000000000000000");
|
BOOST_REQUIRE_EQUAL(test.format("", true), "// f(bytes32): 0x31 -> 0x3200000000000000000000000000000000000000000000000000000000000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(format_hex_string_singleline)
|
||||||
|
{
|
||||||
|
bytes expectedBytes = fromHex("4200ef");
|
||||||
|
ABIType abiType{ABIType::HexString, ABIType::AlignLeft, 3};
|
||||||
|
Parameter param{expectedBytes, "hex\"4200ef\"", abiType, FormatInfo{}};
|
||||||
|
FunctionCallExpectations expectations{vector<Parameter>{param}, false, string{}};
|
||||||
|
FunctionCallArgs arguments{vector<Parameter>{param}, string{}};
|
||||||
|
FunctionCall call{"f(string)", 0, arguments, expectations};
|
||||||
|
TestFunctionCall test{call};
|
||||||
|
|
||||||
|
BOOST_REQUIRE_EQUAL(test.format(), "// f(string): hex\"4200ef\" -> hex\"4200ef\"");
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(format_bool_true_singleline)
|
BOOST_AUTO_TEST_CASE(format_bool_true_singleline)
|
||||||
{
|
{
|
||||||
bytes expectedBytes = toBigEndian(u256{true});
|
bytes expectedBytes = toBigEndian(u256{true});
|
||||||
|
Loading…
Reference in New Issue
Block a user