[isoltest] Refactors parameter formatting.

This commit is contained in:
Erik Kundt 2019-08-14 21:05:26 +02:00
parent 18157f5a49
commit 6c73bc5bac
6 changed files with 89 additions and 36 deletions

View File

@ -1,6 +1,8 @@
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
contract C { contract C {
function d() public {
}
function e() public payable returns (uint) { function e() public payable returns (uint) {
return msg.value; return msg.value;
} }
@ -27,6 +29,7 @@ contract C {
} }
} }
// ---- // ----
// d() ->
// e(), 1 ether -> 1 // e(), 1 ether -> 1
// f(uint256): 3 -> 3, 3 // f(uint256): 3 -> 3, 3
// g() -> 2, 3 // g() -> 2, 3

View File

@ -17,6 +17,7 @@
#include <test/libsolidity/util/BytesUtils.h> #include <test/libsolidity/util/BytesUtils.h>
#include <test/libsolidity/util/ContractABIUtils.h>
#include <test/libsolidity/util/SoltestErrors.h> #include <test/libsolidity/util/SoltestErrors.h>
#include <liblangutil/Common.h> #include <liblangutil/Common.h>
@ -202,29 +203,25 @@ string BytesUtils::formatString(bytes const& _bytes, size_t _cutOff)
return os.str(); return os.str();
} }
string BytesUtils::formatRawBytes(bytes const& _bytes, string _linePrefix, bool _withSignature) string BytesUtils::formatRawBytes(
bytes const& _bytes,
dev::solidity::test::ParameterList const& _parameters,
string _linePrefix)
{ {
if (_bytes.empty()) soltestAssert(_bytes.size() == ContractABIUtils::encodingSize(_parameters), "");
return _linePrefix + "[]";
stringstream os; stringstream os;
auto it = _bytes.begin(); auto it = _bytes.begin();
if (_withSignature) for (auto const& parameter: _parameters)
{ {
os << _linePrefix << bytes{it, it + 4} << endl; bytes byteRange{it, it + static_cast<long>(parameter.abiType.size)};
it += 4;
}
bytes tail{it, _bytes.end()}; os << _linePrefix << byteRange;
it = tail.begin(); if (&parameter != &_parameters.back())
for (size_t i = 0; i < tail.size(); i += 32)
{
os << _linePrefix << bytes{it, it + 32};
it += 32;
if (it != tail.end())
os << endl; os << endl;
it += static_cast<long>(parameter.abiType.size);
} }
return os.str(); return os.str();
@ -278,6 +275,8 @@ string BytesUtils::formatBytesRange(
bool _highlight bool _highlight
) )
{ {
soltestAssert(_bytes.size() == ContractABIUtils::encodingSize(_parameters), "");
stringstream os; stringstream os;
auto it = _bytes.begin(); auto it = _bytes.begin();

View File

@ -106,8 +106,8 @@ public:
/// If _withSignature is true, the first 4 bytes will be formatted separately. /// If _withSignature is true, the first 4 bytes will be formatted separately.
static std::string formatRawBytes( static std::string formatRawBytes(
bytes const& _bytes, bytes const& _bytes,
std::string _linePrefix = "", ParameterList const& _parameters,
bool _withSignature = false std::string _linePrefix = ""
); );
/// Formats given _bytes with type information passed in _abiType. /// Formats given _bytes with type information passed in _abiType.

View File

@ -289,16 +289,47 @@ dev::solidity::test::ParameterList ContractABIUtils::preferredParameters(
{ {
if (_targetParameters.size() != _sourceParameters.size()) if (_targetParameters.size() != _sourceParameters.size())
{ {
auto sizeFold = [](size_t const _a, Parameter const& _b) { return _a + _b.abiType.size; };
size_t encodingSize = accumulate(_targetParameters.begin(), _targetParameters.end(), size_t{0}, sizeFold);
_errorReporter.warning( _errorReporter.warning(
"Encoding does not match byte range. The call returned " + "Encoding does not match byte range. The call returned " +
to_string(_bytes.size()) + " bytes, but " + to_string(_bytes.size()) + " bytes, but " +
to_string(encodingSize) + " bytes were expected." to_string(encodingSize(_targetParameters)) + " bytes were expected."
); );
return _sourceParameters; return _sourceParameters;
} }
else else
return _targetParameters; return _targetParameters;
} }
dev::solidity::test::ParameterList ContractABIUtils::defaultParameters(size_t count)
{
ParameterList parameters;
fill_n(
back_inserter(parameters),
count,
Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}}
);
return parameters;
}
dev::solidity::test::ParameterList ContractABIUtils::failureParameters()
{
ParameterList parameters;
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::HexString, ABIType::AlignNone, 4}, FormatInfo{}});
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}});
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}});
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::String}, FormatInfo{}});
return parameters;
}
size_t ContractABIUtils::encodingSize(
dev::solidity::test::ParameterList const& _parameters
)
{
auto sizeFold = [](size_t const _a, Parameter const& _b) { return _a + _b.abiType.size; };
return accumulate(_parameters.begin(), _parameters.end(), size_t{0}, sizeFold);
}

View File

@ -65,6 +65,18 @@ public:
bytes const& _bytes bytes const& _bytes
); );
/// Returns a list of parameters corresponding to the encoding of
/// returned values in case of a failure.
static ParameterList failureParameters();
/// Returns _count parameters with their type set to ABIType::UnsignedDec
/// and their size set to 32 bytes.
static ParameterList defaultParameters(size_t count = 0);
/// Calculates the encoding size of given _parameters based
/// on the size of their types.
static size_t encodingSize(ParameterList const& _paremeters);
private: private:
/// Parses and translates a single type and returns a list of /// Parses and translates a single type and returns a list of
/// internal type representations of isoltest. /// internal type representations of isoltest.

View File

@ -124,9 +124,24 @@ string TestFunctionCall::format(
if (!matchesExpectation()) if (!matchesExpectation())
{ {
boost::optional<ParameterList> abiParams;
if (isFailure && !output.empty())
abiParams = boost::make_optional(ContractABIUtils::failureParameters());
else
abiParams = ContractABIUtils::parametersFromJsonOutputs(
_errorReporter,
m_contractABI,
m_call.signature
);
string bytesOutput = abiParams ?
BytesUtils::formatRawBytes(output, abiParams.get(), _linePrefix) :
_linePrefix + "[]";
_errorReporter.warning( _errorReporter.warning(
"The call to \"" + m_call.signature + "\" returned \n" + "The call to \"" + m_call.signature + "\" returned \n" +
BytesUtils::formatRawBytes(output, _linePrefix, isFailure && !output.empty()) bytesOutput
); );
} }
@ -176,14 +191,11 @@ string TestFunctionCall::formatBytesParameters(
if (_failure) if (_failure)
{ {
ParameterList defaultParameters; os << BytesUtils::formatBytesRange(
_bytes,
defaultParameters.push_back(Parameter{bytes(), "", ABIType{ABIType::HexString, ABIType::AlignNone, 4}, FormatInfo{}}); ContractABIUtils::failureParameters(),
defaultParameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}}); _highlight
defaultParameters.push_back(Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}}); );
defaultParameters.push_back(Parameter{bytes(), "", ABIType{ABIType::String}, FormatInfo{}});
os << BytesUtils::formatBytesRange(_bytes, defaultParameters, _highlight);
return os.str(); return os.str();
} }
@ -212,12 +224,8 @@ string TestFunctionCall::formatBytesParameters(
} }
else else
{ {
ParameterList defaultParameters; ParameterList defaultParameters = ContractABIUtils::defaultParameters(ceil(_bytes.size() / 32));
fill_n(
back_inserter(defaultParameters),
ceil(_bytes.size() / 32),
Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}}
);
ContractABIUtils::overwriteParameters(_errorReporter, defaultParameters, _parameters); ContractABIUtils::overwriteParameters(_errorReporter, defaultParameters, _parameters);
os << BytesUtils::formatBytesRange(_bytes, defaultParameters, _highlight); os << BytesUtils::formatBytesRange(_bytes, defaultParameters, _highlight);
} }