mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Restructures alignment and bytes utils in isoltest.
This commit is contained in:
parent
de34f7712d
commit
d06be2c53f
@ -163,3 +163,36 @@ string BytesUtils::formatString(bytes const& _bytes) const
|
|||||||
|
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bytes BytesUtils::alignLeft(bytes _bytes) const
|
||||||
|
{
|
||||||
|
return std::move(_bytes) + bytes(32 - _bytes.size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes BytesUtils::alignRight(bytes _bytes) const
|
||||||
|
{
|
||||||
|
return bytes(32 - _bytes.size(), 0) + std::move(_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes BytesUtils::applyAlign(
|
||||||
|
Parameter::Alignment _alignment,
|
||||||
|
ABIType& _abiType,
|
||||||
|
bytes _bytes
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (_alignment != Parameter::Alignment::None)
|
||||||
|
_abiType.alignDeclared = true;
|
||||||
|
|
||||||
|
switch (_alignment)
|
||||||
|
{
|
||||||
|
case Parameter::Alignment::Left:
|
||||||
|
_abiType.align = ABIType::AlignLeft;
|
||||||
|
return alignLeft(std::move(_bytes));
|
||||||
|
case Parameter::Alignment::Right:
|
||||||
|
_abiType.align = ABIType::AlignRight;
|
||||||
|
return alignRight(std::move(_bytes));
|
||||||
|
default:
|
||||||
|
_abiType.align = ABIType::AlignRight;
|
||||||
|
return alignRight(std::move(_bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -77,6 +77,22 @@ public:
|
|||||||
/// string representation of a byte array which is assumed to hold
|
/// string representation of a byte array which is assumed to hold
|
||||||
/// a string value.
|
/// a string value.
|
||||||
std::string formatString(bytes const& _bytes) const;
|
std::string formatString(bytes const& _bytes) const;
|
||||||
|
|
||||||
|
/// Left-aligns and pads given _bytes and returns a new
|
||||||
|
/// bytes array.
|
||||||
|
bytes alignLeft(bytes _bytes) const;
|
||||||
|
|
||||||
|
/// Right-aligns and pads given _bytes and returns a new
|
||||||
|
/// bytes array.
|
||||||
|
bytes alignRight(bytes _bytes) const;
|
||||||
|
|
||||||
|
/// Applies given _alignment to _bytes and returns a new
|
||||||
|
/// bytes array.
|
||||||
|
bytes applyAlign(
|
||||||
|
Parameter::Alignment _alignment,
|
||||||
|
ABIType& _abiType,
|
||||||
|
bytes _bytes
|
||||||
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,13 @@ struct FormatInfo
|
|||||||
*/
|
*/
|
||||||
struct Parameter
|
struct Parameter
|
||||||
{
|
{
|
||||||
|
enum Alignment
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
None,
|
||||||
|
};
|
||||||
|
|
||||||
/// ABI encoded / decoded `bytes` of values.
|
/// ABI encoded / decoded `bytes` of values.
|
||||||
/// These `bytes` are used to pass values to function calls
|
/// These `bytes` are used to pass values to function calls
|
||||||
/// and also to store expected return vales. These are
|
/// and also to store expected return vales. These are
|
||||||
@ -151,6 +158,8 @@ struct Parameter
|
|||||||
/// Format info attached to the parameter. It handles newlines given
|
/// Format info attached to the parameter. It handles newlines given
|
||||||
/// in the declaration of it.
|
/// in the declaration of it.
|
||||||
FormatInfo format;
|
FormatInfo format;
|
||||||
|
/// Stores the parsed alignment, which can be either left(...) or right(...).
|
||||||
|
Alignment alignment = Alignment::None;
|
||||||
};
|
};
|
||||||
using ParameterList = std::vector<Parameter>;
|
using ParameterList = std::vector<Parameter>;
|
||||||
|
|
||||||
|
@ -38,45 +38,6 @@ using namespace dev::solidity::test;
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace soltest;
|
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char TestFileParser::Scanner::peek() const noexcept
|
char TestFileParser::Scanner::peek() const noexcept
|
||||||
{
|
{
|
||||||
if (std::distance(m_char, m_line.end()) < 2)
|
if (std::distance(m_char, m_line.end()) < 2)
|
||||||
@ -248,112 +209,124 @@ Parameter TestFileParser::parseParameter()
|
|||||||
if (accept(Token::Newline, true))
|
if (accept(Token::Newline, true))
|
||||||
parameter.format.newline = true;
|
parameter.format.newline = true;
|
||||||
|
|
||||||
auto literal = parseABITypeLiteral();
|
|
||||||
parameter.rawBytes = get<0>(literal);
|
|
||||||
parameter.abiType = get<1>(literal);
|
|
||||||
parameter.rawString = get<2>(literal);
|
|
||||||
|
|
||||||
return parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
bool isSigned = false;
|
||||||
|
|
||||||
if (accept(Token::Left, true))
|
if (accept(Token::Left, true))
|
||||||
{
|
{
|
||||||
rawString += formatToken(Token::Left);
|
parameter.rawString += formatToken(Token::Left);
|
||||||
expect(Token::LParen);
|
expect(Token::LParen);
|
||||||
rawString += formatToken(Token::LParen);
|
parameter.rawString += formatToken(Token::LParen);
|
||||||
alignment = DeclaredAlignment::Left;
|
parameter.alignment = Parameter::Alignment::Left;
|
||||||
}
|
}
|
||||||
if (accept(Token::Right, true))
|
if (accept(Token::Right, true))
|
||||||
{
|
{
|
||||||
rawString += formatToken(Token::Right);
|
parameter.rawString += formatToken(Token::Right);
|
||||||
expect(Token::LParen);
|
expect(Token::LParen);
|
||||||
rawString += formatToken(Token::LParen);
|
parameter.rawString += formatToken(Token::LParen);
|
||||||
alignment = DeclaredAlignment::Right;
|
parameter.alignment = Parameter::Alignment::Right;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (accept(Token::Sub, true))
|
if (accept(Token::Sub, true))
|
||||||
{
|
{
|
||||||
rawString += formatToken(Token::Sub);
|
parameter.rawString += formatToken(Token::Sub);
|
||||||
isSigned = true;
|
isSigned = true;
|
||||||
}
|
}
|
||||||
if (accept(Token::Boolean))
|
if (accept(Token::Boolean))
|
||||||
{
|
{
|
||||||
if (isSigned)
|
if (isSigned)
|
||||||
throw Error(Error::Type::ParserError, "Invalid boolean literal.");
|
throw Error(Error::Type::ParserError, "Invalid boolean literal.");
|
||||||
abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32};
|
|
||||||
|
parameter.abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32};
|
||||||
string parsed = parseBoolean();
|
string parsed = parseBoolean();
|
||||||
rawString += parsed;
|
parameter.rawString += parsed;
|
||||||
result = applyAlign(alignment, abiType, BytesUtils().convertBoolean(parsed));
|
parameter.rawBytes = BytesUtils().applyAlign(
|
||||||
|
parameter.alignment,
|
||||||
|
parameter.abiType,
|
||||||
|
BytesUtils().convertBoolean(parsed)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (accept(Token::HexNumber))
|
else if (accept(Token::HexNumber))
|
||||||
{
|
{
|
||||||
if (isSigned)
|
if (isSigned)
|
||||||
throw Error(Error::Type::ParserError, "Invalid hex number literal.");
|
throw Error(Error::Type::ParserError, "Invalid hex number literal.");
|
||||||
abiType = ABIType{ABIType::Hex, ABIType::AlignRight, 32};
|
|
||||||
|
parameter.abiType = ABIType{ABIType::Hex, ABIType::AlignRight, 32};
|
||||||
string parsed = parseHexNumber();
|
string parsed = parseHexNumber();
|
||||||
rawString += parsed;
|
parameter.rawString += parsed;
|
||||||
result = applyAlign(alignment, abiType, BytesUtils().convertHexNumber(parsed));
|
parameter.rawBytes = BytesUtils().applyAlign(
|
||||||
|
parameter.alignment,
|
||||||
|
parameter.abiType,
|
||||||
|
BytesUtils().convertHexNumber(parsed)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (accept(Token::Hex, true))
|
else if (accept(Token::Hex, true))
|
||||||
{
|
{
|
||||||
if (isSigned)
|
if (isSigned)
|
||||||
throw Error(Error::Type::ParserError, "Invalid hex string literal.");
|
throw Error(Error::Type::ParserError, "Invalid hex string literal.");
|
||||||
if (alignment != DeclaredAlignment::None)
|
if (parameter.alignment != Parameter::Alignment::None)
|
||||||
throw Error(Error::Type::ParserError, "Hex string literals cannot be aligned or padded.");
|
throw Error(Error::Type::ParserError, "Hex string literals cannot be aligned or padded.");
|
||||||
|
|
||||||
string parsed = parseString();
|
string parsed = parseString();
|
||||||
rawString += "hex\"" + parsed + "\"";
|
parameter.rawString += "hex\"" + parsed + "\"";
|
||||||
result = BytesUtils().convertHexNumber(parsed);
|
parameter.rawBytes = BytesUtils().convertHexNumber(parsed);
|
||||||
abiType = ABIType{ABIType::HexString, ABIType::AlignNone, result.size()};
|
parameter.abiType = ABIType{
|
||||||
|
ABIType::HexString, ABIType::AlignNone, parameter.rawBytes.size()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else if (accept(Token::String))
|
else if (accept(Token::String))
|
||||||
{
|
{
|
||||||
if (isSigned)
|
if (isSigned)
|
||||||
throw Error(Error::Type::ParserError, "Invalid string literal.");
|
throw Error(Error::Type::ParserError, "Invalid string literal.");
|
||||||
if (alignment != DeclaredAlignment::None)
|
if (parameter.alignment != Parameter::Alignment::None)
|
||||||
throw Error(Error::Type::ParserError, "String literals cannot be aligned or padded.");
|
throw Error(Error::Type::ParserError, "String literals cannot be aligned or padded.");
|
||||||
abiType = ABIType{ABIType::String, ABIType::AlignLeft, 32};
|
|
||||||
|
parameter.abiType = ABIType{ABIType::String, ABIType::AlignLeft, 32};
|
||||||
string parsed = parseString();
|
string parsed = parseString();
|
||||||
rawString += "\"" + parsed + "\"";
|
parameter.rawString += "\"" + parsed + "\"";
|
||||||
result = applyAlign(DeclaredAlignment::Left, abiType, BytesUtils().convertString(parsed));
|
parameter.rawBytes = BytesUtils().applyAlign(
|
||||||
|
Parameter::Alignment::Left,
|
||||||
|
parameter.abiType,
|
||||||
|
BytesUtils().convertString(parsed)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (accept(Token::Number))
|
else if (accept(Token::Number))
|
||||||
{
|
{
|
||||||
auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec;
|
auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec;
|
||||||
abiType = ABIType{type, ABIType::AlignRight, 32};
|
|
||||||
|
parameter.abiType = ABIType{type, ABIType::AlignRight, 32};
|
||||||
string parsed = parseDecimalNumber();
|
string parsed = parseDecimalNumber();
|
||||||
rawString += parsed;
|
parameter.rawString += parsed;
|
||||||
if (isSigned)
|
if (isSigned)
|
||||||
parsed = "-" + parsed;
|
parsed = "-" + parsed;
|
||||||
result = applyAlign(alignment, abiType, BytesUtils().convertNumber(parsed));
|
|
||||||
|
parameter.rawBytes = BytesUtils().applyAlign(
|
||||||
|
parameter.alignment,
|
||||||
|
parameter.abiType,
|
||||||
|
BytesUtils().convertNumber(parsed)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (accept(Token::Failure, true))
|
else if (accept(Token::Failure, true))
|
||||||
{
|
{
|
||||||
if (isSigned)
|
if (isSigned)
|
||||||
throw Error(Error::Type::ParserError, "Invalid failure literal.");
|
throw Error(Error::Type::ParserError, "Invalid failure literal.");
|
||||||
abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0};
|
|
||||||
result = bytes{};
|
parameter.abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0};
|
||||||
|
parameter.rawBytes = bytes{};
|
||||||
}
|
}
|
||||||
if (alignment != DeclaredAlignment::None)
|
if (parameter.alignment != Parameter::Alignment::None)
|
||||||
{
|
{
|
||||||
expect(Token::RParen);
|
expect(Token::RParen);
|
||||||
rawString += formatToken(Token::RParen);
|
parameter.rawString += formatToken(Token::RParen);
|
||||||
}
|
}
|
||||||
return make_tuple(result, abiType, rawString);
|
|
||||||
}
|
}
|
||||||
catch (std::exception const&)
|
catch (std::exception const&)
|
||||||
{
|
{
|
||||||
throw Error(Error::Type::ParserError, "Literal encoding invalid.");
|
throw Error(Error::Type::ParserError, "Literal encoding invalid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
string TestFileParser::parseIdentifierOrTuple()
|
string TestFileParser::parseIdentifierOrTuple()
|
||||||
|
@ -146,9 +146,7 @@ private:
|
|||||||
/// appends it to the internal `bytes` buffer of the parameter. It can also
|
/// appends it to the internal `bytes` buffer of the parameter. It can also
|
||||||
/// store newlines found in the source, that are needed to
|
/// store newlines found in the source, that are needed to
|
||||||
/// format input and output of the interactive update.
|
/// format input and output of the interactive update.
|
||||||
Parameter parseParameter();
|
/// Parses and converts the current literal to its byte representation and
|
||||||
|
|
||||||
/// Parses and converts the current literal to its byte representation and
|
|
||||||
/// preserves the chosen ABI type, as well as a raw, unformatted string representation
|
/// preserves the chosen ABI type, as well as a raw, unformatted string representation
|
||||||
/// of this literal.
|
/// of this literal.
|
||||||
/// Based on the type information retrieved, the driver of this parser may format arguments,
|
/// Based on the type information retrieved, the driver of this parser may format arguments,
|
||||||
@ -157,7 +155,7 @@ private:
|
|||||||
/// Returns invalid ABI type for empty literal. This is needed in order
|
/// Returns invalid ABI type for empty literal. This is needed in order
|
||||||
/// to detect empty expectations. Throws a ParserError if data is encoded incorrectly or
|
/// to detect empty expectations. Throws a ParserError if data is encoded incorrectly or
|
||||||
/// if data type is not supported.
|
/// if data type is not supported.
|
||||||
std::tuple<bytes, ABIType, std::string> parseABITypeLiteral();
|
Parameter parseParameter();
|
||||||
|
|
||||||
/// Recursively parses an identifier or a tuple definition that contains identifiers
|
/// Recursively parses an identifier or a tuple definition that contains identifiers
|
||||||
/// and / or parentheses like `((uint, uint), (uint, (uint, uint)), uint)`.
|
/// and / or parentheses like `((uint, uint), (uint, (uint, uint)), uint)`.
|
||||||
|
@ -199,14 +199,6 @@ private:
|
|||||||
std::string const& _linePrefix = ""
|
std::string const& _linePrefix = ""
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
/// If parameter count does not match, take types defined by ABI, but only
|
|
||||||
/// if the contract ABI is defined (needed for format tests where the actual
|
|
||||||
/// result does not matter).
|
|
||||||
ParameterList choosePreferredParameters(
|
|
||||||
ParameterList const& _parsedParamters,
|
|
||||||
ParameterList const& _abiParameters
|
|
||||||
) const;
|
|
||||||
|
|
||||||
/// Compares raw expectations (which are converted to a byte representation before),
|
/// Compares raw expectations (which are converted to a byte representation before),
|
||||||
/// and also the expected transaction status of the function call to the actual test results.
|
/// and also the expected transaction status of the function call to the actual test results.
|
||||||
bool matchesExpectation() const;
|
bool matchesExpectation() const;
|
||||||
|
Loading…
Reference in New Issue
Block a user