Skip to content

Commit d02a26d

Browse files
committed
Moves function call test to separate class.
1 parent 359fcd7 commit d02a26d

6 files changed

+434
-210
lines changed

test/libsolidity/SemanticTest.cpp

+10-179
Original file line numberDiff line numberDiff line change
@@ -35,175 +35,6 @@ using namespace boost::algorithm;
3535
using namespace boost::unit_test;
3636
namespace fs = boost::filesystem;
3737

38-
namespace
39-
{
40-
using FunctionCallTest = SemanticTest::FunctionCallTest;
41-
using FunctionCall = dev::solidity::test::FunctionCall;
42-
using ParamList = dev::solidity::test::ParameterList;
43-
44-
45-
string formatBytes(bytes const& _bytes, ParamList const& _params)
46-
{
47-
stringstream resultStream;
48-
if (_bytes.empty())
49-
return {};
50-
auto it = _bytes.begin();
51-
for (auto const& param: _params)
52-
{
53-
long offset = static_cast<long>(param.abiType.size);
54-
auto offsetIter = it + offset;
55-
soltestAssert(offsetIter <= _bytes.end(), "Byte range can not be extended past the end of given bytes.");
56-
57-
bytes byteRange{it, offsetIter};
58-
switch (param.abiType.type)
59-
{
60-
case ABIType::SignedDec:
61-
soltestAssert(param.abiType.align == ABIType::AlignRight, "");
62-
if (*byteRange.begin() & 0x80)
63-
resultStream << u2s(fromBigEndian<u256>(byteRange));
64-
else
65-
resultStream << fromBigEndian<u256>(byteRange);
66-
break;
67-
case ABIType::UnsignedDec:
68-
// Check if the detected type was wrong and if this could
69-
// be signed. If an unsigned was detected in the expectations,
70-
// but the actual result returned a signed, it would be formatted
71-
// incorrectly.
72-
soltestAssert(param.abiType.align == ABIType::AlignRight, "");
73-
if (*byteRange.begin() & 0x80)
74-
resultStream << u2s(fromBigEndian<u256>(byteRange));
75-
else
76-
resultStream << fromBigEndian<u256>(byteRange);
77-
break;
78-
case ABIType::Hex:
79-
soltestAssert(param.abiType.align == ABIType::AlignLeft, "");
80-
byteRange.erase(
81-
std::remove(byteRange.begin(), byteRange.end(), 0), byteRange.end()
82-
);
83-
resultStream << toHex(byteRange, HexPrefix::Add);
84-
break;
85-
case ABIType::Failure:
86-
break;
87-
case ABIType::None:
88-
break;
89-
}
90-
it += offset;
91-
if (it != _bytes.end() && !(param.abiType.type == ABIType::None))
92-
resultStream << ", ";
93-
}
94-
soltestAssert(it == _bytes.end(), "Parameter encoding too short for the given byte range.");
95-
return resultStream.str();
96-
}
97-
98-
string formatRawArguments(ParamList const& _params, string const& _linePrefix = "")
99-
{
100-
stringstream resultStream;
101-
for (auto const& param: _params)
102-
{
103-
if (param.format.newline)
104-
resultStream << endl << _linePrefix << "//";
105-
resultStream << " " << param.rawString;
106-
if (&param != &_params.back())
107-
resultStream << ",";
108-
}
109-
return resultStream.str();
110-
}
111-
112-
string formatFunctionCallTest(
113-
FunctionCallTest const& _test,
114-
string const& _linePrefix = "",
115-
bool const _renderResult = false,
116-
bool const _highlight = false
117-
)
118-
{
119-
using namespace soltest;
120-
using Token = soltest::Token;
121-
122-
stringstream _stream;
123-
FunctionCall call = _test.call;
124-
bool highlight = !_test.matchesExpectation() && _highlight;
125-
126-
auto formatOutput = [&](bool const _singleLine)
127-
{
128-
string ws = " ";
129-
string arrow = formatToken(Token::Arrow);
130-
string colon = formatToken(Token::Colon);
131-
string comma = formatToken(Token::Comma);
132-
string comment = formatToken(Token::Comment);
133-
string ether = formatToken(Token::Ether);
134-
string newline = formatToken(Token::Newline);
135-
string failure = formatToken(Token::Failure);
136-
137-
/// Prints the function signature. This is the same independent from the display-mode.
138-
_stream << _linePrefix << newline << ws << call.signature;
139-
if (call.value > u256(0))
140-
_stream << comma << ws << call.value << ws << ether;
141-
if (!call.arguments.rawBytes().empty())
142-
{
143-
string output = formatRawArguments(call.arguments.parameters, _linePrefix);
144-
_stream << colon << output;
145-
}
146-
147-
/// Prints comments on the function parameters and the arrow taking
148-
/// the display-mode into account.
149-
if (_singleLine)
150-
{
151-
if (!call.arguments.comment.empty())
152-
_stream << ws << comment << call.arguments.comment << comment;
153-
_stream << ws << arrow << ws;
154-
}
155-
else
156-
{
157-
_stream << endl << _linePrefix << newline << ws;
158-
if (!call.arguments.comment.empty())
159-
{
160-
_stream << comment << call.arguments.comment << comment;
161-
_stream << endl << _linePrefix << newline << ws;
162-
}
163-
_stream << arrow << ws;
164-
}
165-
166-
/// Print either the expected output or the actual result output
167-
string result;
168-
if (!_renderResult)
169-
{
170-
bytes output = call.expectations.rawBytes();
171-
bool const isFailure = call.expectations.failure;
172-
result = isFailure ? failure : formatBytes(output, call.expectations.result);
173-
}
174-
else
175-
{
176-
bytes output = _test.rawBytes;
177-
bool const isFailure = _test.failure;
178-
result = isFailure ? failure : formatBytes(output, call.expectations.result);
179-
}
180-
AnsiColorized(_stream, highlight, {RED_BACKGROUND}) << result;
181-
182-
/// Print comments on expectations taking the display-mode into account.
183-
if (_singleLine)
184-
{
185-
if (!call.expectations.comment.empty())
186-
_stream << ws << comment << call.expectations.comment << comment;
187-
}
188-
else
189-
{
190-
if (!call.expectations.comment.empty())
191-
{
192-
_stream << endl << _linePrefix << newline << ws;
193-
_stream << comment << call.expectations.comment << comment;
194-
}
195-
}
196-
};
197-
198-
if (call.displayMode == FunctionCall::DisplayMode::SingleLine)
199-
formatOutput(true);
200-
else
201-
formatOutput(false);
202-
_stream << endl;
203-
204-
return _stream.str();
205-
}
206-
}
20738

20839
SemanticTest::SemanticTest(string const& _filename, string const& _ipcPath):
20940
SolidityExecutionFramework(_ipcPath)
@@ -227,27 +58,27 @@ bool SemanticTest::run(ostream& _stream, string const& _linePrefix, bool const _
22758
for (auto& test: m_tests)
22859
{
22960
bytes output = callContractFunctionWithValueNoEncoding(
230-
test.call.signature,
231-
test.call.value,
232-
test.call.arguments.rawBytes()
61+
test.call().signature,
62+
test.call().value,
63+
test.call().arguments.rawBytes()
23364
);
23465

235-
if ((m_transactionSuccessful == test.call.expectations.failure) || (output != test.call.expectations.rawBytes()))
66+
if ((m_transactionSuccessful == test.call().expectations.failure) || (output != test.call().expectations.rawBytes()))
23667
success = false;
23768

238-
test.failure = !m_transactionSuccessful;
239-
test.rawBytes = std::move(output);
69+
test.setFailure(!m_transactionSuccessful);
70+
test.setRawBytes(std::move(output));
24071
}
24172

24273
if (!success)
24374
{
24475
AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl;
24576
for (auto const& test: m_tests)
246-
_stream << formatFunctionCallTest(test, _linePrefix, false, true & _formatted);
77+
_stream << test.format(_linePrefix, false, true & _formatted) << endl;
24778

24879
AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl;
24980
for (auto const& test: m_tests)
250-
_stream << formatFunctionCallTest(test, _linePrefix, true, true & _formatted);
81+
_stream << test.format(_linePrefix, true, true & _formatted) << endl;
25182

25283
AnsiColorized(_stream, _formatted, {BOLD, RED}) << _linePrefix
25384
<< "Attention: Updates on the test will apply the detected format displayed." << endl;
@@ -267,14 +98,14 @@ void SemanticTest::printSource(ostream& _stream, string const& _linePrefix, bool
26798
void SemanticTest::printUpdatedExpectations(ostream& _stream, string const&) const
26899
{
269100
for (auto const& test: m_tests)
270-
_stream << formatFunctionCallTest(test, "", true, false);
101+
_stream << test.format("", true, false) << endl;
271102
}
272103

273104
void SemanticTest::parseExpectations(istream& _stream)
274105
{
275106
TestFileParser parser{_stream};
276107
for (auto const& call: parser.parseFunctionCalls())
277-
m_tests.emplace_back(FunctionCallTest{call, bytes{}, string{}});
108+
m_tests.emplace_back(TestFunctionCall{call});
278109
}
279110

280111
bool SemanticTest::deploy(string const& _contractName, u256 const& _value, bytes const& _arguments)

test/libsolidity/SemanticTest.h

+3-30
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#pragma once
1616

1717
#include <test/libsolidity/util/TestFileParser.h>
18+
#include <test/libsolidity/util/TestFunctionCall.h>
1819
#include <test/libsolidity/SolidityExecutionFramework.h>
1920
#include <test/libsolidity/AnalysisFramework.h>
2021
#include <test/TestCase.h>
@@ -42,35 +43,6 @@ namespace test
4243
class SemanticTest: public SolidityExecutionFramework, public TestCase
4344
{
4445
public:
45-
/**
46-
* Represents a function call and the result it returned. It stores the call
47-
* representation itself, the actual byte result (if any) and a string representation
48-
* used for the interactive update routine provided by isoltest. It also provides
49-
* functionality to compare the actual result with the expectations attached to the
50-
* call object, as well as a way to reset the result if executed multiple times.
51-
*/
52-
struct FunctionCallTest
53-
{
54-
FunctionCall call;
55-
bytes rawBytes;
56-
std::string output;
57-
bool failure = true;
58-
/// Compares raw expectations (which are converted to a byte representation before),
59-
/// and also the expected transaction status of the function call to the actual test results.
60-
bool matchesExpectation() const
61-
{
62-
return failure == call.expectations.failure && rawBytes == call.expectations.rawBytes();
63-
}
64-
/// Resets current results in case the function was called and the result
65-
/// stored already (e.g. if test case was updated via isoltest).
66-
void reset()
67-
{
68-
failure = true;
69-
rawBytes = bytes{};
70-
output = std::string{};
71-
}
72-
};
73-
7446
static std::unique_ptr<TestCase> create(Config const& _options)
7547
{ return std::make_unique<SemanticTest>(_options.filename, _options.ipcPath); }
7648

@@ -90,8 +62,9 @@ class SemanticTest: public SolidityExecutionFramework, public TestCase
9062
/// Returns true if deployment was successful, false otherwise.
9163
bool deploy(std::string const& _contractName, u256 const& _value, bytes const& _arguments);
9264

65+
private:
9366
std::string m_source;
94-
std::vector<FunctionCallTest> m_tests;
67+
std::vector<TestFunctionCall> m_tests;
9568
};
9669

9770
}

0 commit comments

Comments
 (0)