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();
|
||||
}
|
||||
|
||||
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
|
||||
/// a string value.
|
||||
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
|
||||
{
|
||||
enum Alignment
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
None,
|
||||
};
|
||||
|
||||
/// ABI encoded / decoded `bytes` of values.
|
||||
/// These `bytes` are used to pass values to function calls
|
||||
/// 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
|
||||
/// in the declaration of it.
|
||||
FormatInfo format;
|
||||
/// Stores the parsed alignment, which can be either left(...) or right(...).
|
||||
Alignment alignment = Alignment::None;
|
||||
};
|
||||
using ParameterList = std::vector<Parameter>;
|
||||
|
||||
|
@ -38,45 +38,6 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char TestFileParser::Scanner::peek() const noexcept
|
||||
{
|
||||
if (std::distance(m_char, m_line.end()) < 2)
|
||||
@ -248,112 +209,124 @@ Parameter TestFileParser::parseParameter()
|
||||
if (accept(Token::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;
|
||||
|
||||
if (accept(Token::Left, true))
|
||||
{
|
||||
rawString += formatToken(Token::Left);
|
||||
parameter.rawString += formatToken(Token::Left);
|
||||
expect(Token::LParen);
|
||||
rawString += formatToken(Token::LParen);
|
||||
alignment = DeclaredAlignment::Left;
|
||||
parameter.rawString += formatToken(Token::LParen);
|
||||
parameter.alignment = Parameter::Alignment::Left;
|
||||
}
|
||||
if (accept(Token::Right, true))
|
||||
{
|
||||
rawString += formatToken(Token::Right);
|
||||
parameter.rawString += formatToken(Token::Right);
|
||||
expect(Token::LParen);
|
||||
rawString += formatToken(Token::LParen);
|
||||
alignment = DeclaredAlignment::Right;
|
||||
parameter.rawString += formatToken(Token::LParen);
|
||||
parameter.alignment = Parameter::Alignment::Right;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (accept(Token::Sub, true))
|
||||
{
|
||||
rawString += formatToken(Token::Sub);
|
||||
parameter.rawString += formatToken(Token::Sub);
|
||||
isSigned = true;
|
||||
}
|
||||
if (accept(Token::Boolean))
|
||||
{
|
||||
if (isSigned)
|
||||
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();
|
||||
rawString += parsed;
|
||||
result = applyAlign(alignment, abiType, BytesUtils().convertBoolean(parsed));
|
||||
parameter.rawString += parsed;
|
||||
parameter.rawBytes = BytesUtils().applyAlign(
|
||||
parameter.alignment,
|
||||
parameter.abiType,
|
||||
BytesUtils().convertBoolean(parsed)
|
||||
);
|
||||
}
|
||||
else if (accept(Token::HexNumber))
|
||||
{
|
||||
if (isSigned)
|
||||
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();
|
||||
rawString += parsed;
|
||||
result = applyAlign(alignment, abiType, BytesUtils().convertHexNumber(parsed));
|
||||
parameter.rawString += parsed;
|
||||
parameter.rawBytes = BytesUtils().applyAlign(
|
||||
parameter.alignment,
|
||||
parameter.abiType,
|
||||
BytesUtils().convertHexNumber(parsed)
|
||||
);
|
||||
}
|
||||
else if (accept(Token::Hex, true))
|
||||
{
|
||||
if (isSigned)
|
||||
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.");
|
||||
|
||||
string parsed = parseString();
|
||||
rawString += "hex\"" + parsed + "\"";
|
||||
result = BytesUtils().convertHexNumber(parsed);
|
||||
abiType = ABIType{ABIType::HexString, ABIType::AlignNone, result.size()};
|
||||
parameter.rawString += "hex\"" + parsed + "\"";
|
||||
parameter.rawBytes = BytesUtils().convertHexNumber(parsed);
|
||||
parameter.abiType = ABIType{
|
||||
ABIType::HexString, ABIType::AlignNone, parameter.rawBytes.size()
|
||||
};
|
||||
}
|
||||
else if (accept(Token::String))
|
||||
{
|
||||
if (isSigned)
|
||||
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.");
|
||||
abiType = ABIType{ABIType::String, ABIType::AlignLeft, 32};
|
||||
|
||||
parameter.abiType = ABIType{ABIType::String, ABIType::AlignLeft, 32};
|
||||
string parsed = parseString();
|
||||
rawString += "\"" + parsed + "\"";
|
||||
result = applyAlign(DeclaredAlignment::Left, abiType, BytesUtils().convertString(parsed));
|
||||
parameter.rawString += "\"" + parsed + "\"";
|
||||
parameter.rawBytes = BytesUtils().applyAlign(
|
||||
Parameter::Alignment::Left,
|
||||
parameter.abiType,
|
||||
BytesUtils().convertString(parsed)
|
||||
);
|
||||
}
|
||||
else if (accept(Token::Number))
|
||||
{
|
||||
auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec;
|
||||
abiType = ABIType{type, ABIType::AlignRight, 32};
|
||||
|
||||
parameter.abiType = ABIType{type, ABIType::AlignRight, 32};
|
||||
string parsed = parseDecimalNumber();
|
||||
rawString += parsed;
|
||||
parameter.rawString += parsed;
|
||||
if (isSigned)
|
||||
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))
|
||||
{
|
||||
if (isSigned)
|
||||
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);
|
||||
rawString += formatToken(Token::RParen);
|
||||
parameter.rawString += formatToken(Token::RParen);
|
||||
}
|
||||
return make_tuple(result, abiType, rawString);
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
throw Error(Error::Type::ParserError, "Literal encoding invalid.");
|
||||
}
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
string TestFileParser::parseIdentifierOrTuple()
|
||||
|
@ -146,9 +146,7 @@ private:
|
||||
/// appends it to the internal `bytes` buffer of the parameter. It can also
|
||||
/// store newlines found in the source, that are needed to
|
||||
/// 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
|
||||
/// of this literal.
|
||||
/// 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
|
||||
/// to detect empty expectations. Throws a ParserError if data is encoded incorrectly or
|
||||
/// 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
|
||||
/// and / or parentheses like `((uint, uint), (uint, (uint, uint)), uint)`.
|
||||
|
@ -199,14 +199,6 @@ private:
|
||||
std::string const& _linePrefix = ""
|
||||
) 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),
|
||||
/// and also the expected transaction status of the function call to the actual test results.
|
||||
bool matchesExpectation() const;
|
||||
|
Loading…
Reference in New Issue
Block a user