Skip to content

Commit 54d6804

Browse files
committed
Moves function call test to separate class.
1 parent 6c7ad42 commit 54d6804

8 files changed

+426
-206
lines changed

test/libsolidity/SemanticTest.cpp

+10-170
Original file line numberDiff line numberDiff line change
@@ -35,166 +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-
if (*byteRange.begin() & 0x80)
62-
resultStream << u2s(fromBigEndian<u256>(byteRange));
63-
else
64-
resultStream << fromBigEndian<u256>(byteRange);
65-
break;
66-
case ABIType::UnsignedDec:
67-
// Check if the detected type was wrong and if this could
68-
// be signed. If an unsigned was detected in the expectations,
69-
// but the actual result returned a signed, it would be formatted
70-
// incorrectly.
71-
if (*byteRange.begin() & 0x80)
72-
resultStream << u2s(fromBigEndian<u256>(byteRange));
73-
else
74-
resultStream << fromBigEndian<u256>(byteRange);
75-
break;
76-
case ABIType::Failure:
77-
break;
78-
case ABIType::None:
79-
break;
80-
}
81-
it += offset;
82-
if (it != _bytes.end() && !(param.abiType.type == ABIType::None))
83-
resultStream << ", ";
84-
}
85-
soltestAssert(it == _bytes.end(), "Parameter encoding too short for the given byte range.");
86-
return resultStream.str();
87-
}
88-
89-
string formatRawArguments(ParamList const& _params, string const& _linePrefix = "")
90-
{
91-
stringstream resultStream;
92-
for (auto const& param: _params)
93-
{
94-
if (param.format.newline)
95-
resultStream << endl << _linePrefix << "//";
96-
resultStream << " " << param.rawString;
97-
if (&param != &_params.back())
98-
resultStream << ",";
99-
}
100-
return resultStream.str();
101-
}
102-
103-
string formatFunctionCallTest(
104-
FunctionCallTest const& _test,
105-
string const& _linePrefix = "",
106-
bool const _renderResult = false,
107-
bool const _highlight = false
108-
)
109-
{
110-
using namespace soltest;
111-
using Token = soltest::Token;
112-
113-
stringstream _stream;
114-
FunctionCall call = _test.call;
115-
bool highlight = !_test.matchesExpectation() && _highlight;
116-
117-
auto formatOutput = [&](bool const _singleLine)
118-
{
119-
string ws = " ";
120-
string arrow = formatToken(Token::Arrow);
121-
string colon = formatToken(Token::Colon);
122-
string comma = formatToken(Token::Comma);
123-
string comment = formatToken(Token::Comment);
124-
string ether = formatToken(Token::Ether);
125-
string newline = formatToken(Token::Newline);
126-
string failure = formatToken(Token::Failure);
127-
128-
/// Prints the function signature. This is the same independent from the display-mode.
129-
_stream << _linePrefix << newline << ws << call.signature;
130-
if (call.value > u256(0))
131-
_stream << comma << ws << call.value << ws << ether;
132-
if (!call.arguments.rawBytes().empty())
133-
{
134-
string output = formatRawArguments(call.arguments.parameters, _linePrefix);
135-
_stream << colon << output;
136-
}
137-
138-
/// Prints comments on the function parameters and the arrow taking
139-
/// the display-mode into account.
140-
if (_singleLine)
141-
{
142-
if (!call.arguments.comment.empty())
143-
_stream << ws << comment << call.arguments.comment << comment;
144-
_stream << ws << arrow << ws;
145-
}
146-
else
147-
{
148-
_stream << endl << _linePrefix << newline << ws;
149-
if (!call.arguments.comment.empty())
150-
{
151-
_stream << comment << call.arguments.comment << comment;
152-
_stream << endl << _linePrefix << newline << ws;
153-
}
154-
_stream << arrow << ws;
155-
}
156-
157-
/// Print either the expected output or the actual result output
158-
string result;
159-
if (!_renderResult)
160-
{
161-
bytes output = call.expectations.rawBytes();
162-
bool const isFailure = call.expectations.failure;
163-
result = isFailure ? failure : formatBytes(output, call.expectations.result);
164-
}
165-
else
166-
{
167-
bytes output = _test.rawBytes;
168-
bool const isFailure = _test.failure;
169-
result = isFailure ? failure : formatBytes(output, call.expectations.result);
170-
}
171-
AnsiColorized(_stream, highlight, {RED_BACKGROUND}) << result;
172-
173-
/// Print comments on expectations taking the display-mode into account.
174-
if (_singleLine)
175-
{
176-
if (!call.expectations.comment.empty())
177-
_stream << ws << comment << call.expectations.comment << comment;
178-
}
179-
else
180-
{
181-
if (!call.expectations.comment.empty())
182-
{
183-
_stream << endl << _linePrefix << newline << ws;
184-
_stream << comment << call.expectations.comment << comment;
185-
}
186-
}
187-
};
188-
189-
if (call.displayMode == FunctionCall::DisplayMode::SingleLine)
190-
formatOutput(true);
191-
else
192-
formatOutput(false);
193-
_stream << endl;
194-
195-
return _stream.str();
196-
}
197-
}
19838

19939
SemanticTest::SemanticTest(string const& _filename, string const& _ipcPath):
20040
SolidityExecutionFramework(_ipcPath)
@@ -218,27 +58,27 @@ bool SemanticTest::run(ostream& _stream, string const& _linePrefix, bool const _
21858
for (auto& test: m_tests)
21959
{
22060
bytes output = callContractFunctionWithValueNoEncoding(
221-
test.call.signature,
222-
test.call.value,
223-
test.call.arguments.rawBytes()
61+
test.call().signature,
62+
test.call().value,
63+
test.call().arguments.rawBytes()
22464
);
22565

226-
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()))
22767
success = false;
22868

229-
test.failure = !m_transactionSuccessful;
230-
test.rawBytes = std::move(output);
69+
test.setFailure(!m_transactionSuccessful);
70+
test.setRawBytes(std::move(output));
23171
}
23272

23373
if (!success)
23474
{
23575
AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl;
23676
for (auto const& test: m_tests)
237-
_stream << formatFunctionCallTest(test, _linePrefix, false, true & _formatted);
77+
_stream << test.format(_linePrefix, false, true & _formatted) << endl;
23878

23979
AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl;
24080
for (auto const& test: m_tests)
241-
_stream << formatFunctionCallTest(test, _linePrefix, true, true & _formatted);
81+
_stream << test.format(_linePrefix, true, true & _formatted) << endl;
24282

24383
AnsiColorized(_stream, _formatted, {BOLD, RED}) << _linePrefix
24484
<< "Attention: Updates on the test will apply the detected format displayed." << endl;
@@ -258,14 +98,14 @@ void SemanticTest::printSource(ostream& _stream, string const& _linePrefix, bool
25898
void SemanticTest::printUpdatedExpectations(ostream& _stream, string const&) const
25999
{
260100
for (auto const& test: m_tests)
261-
_stream << formatFunctionCallTest(test, "", true, false);
101+
_stream << test.format("", true, false) << endl;
262102
}
263103

264104
void SemanticTest::parseExpectations(istream& _stream)
265105
{
266106
TestFileParser parser{_stream};
267107
for (auto const& call: parser.parseFunctionCalls())
268-
m_tests.emplace_back(FunctionCallTest{call, bytes{}, string{}});
108+
m_tests.emplace_back(TestFunctionCall{call});
269109
}
270110

271111
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
}

test/libsolidity/util/TestFileParser.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
195195
try
196196
{
197197
u256 number{0};
198-
ABIType abiType{ABIType::None, 0};
198+
ABIType abiType{ABIType::None, ABIType::AlignRight, 0};
199199
string rawString;
200200

201201
if (accept(Token::Sub))
202202
{
203-
abiType = ABIType{ABIType::SignedDec, 32};
203+
abiType = ABIType{ABIType::SignedDec, ABIType::AlignRight, 32};
204204
expect(Token::Sub);
205205
rawString += formatToken(Token::Sub);
206206
string parsed = parseNumber();
@@ -211,14 +211,14 @@ tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
211211
{
212212
if (accept(Token::Number))
213213
{
214-
abiType = ABIType{ABIType::UnsignedDec, 32};
214+
abiType = ABIType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
215215
string parsed = parseNumber();
216216
rawString += parsed;
217217
number = convertNumber(parsed);
218218
}
219219
else if (accept(Token::Failure, true))
220220
{
221-
abiType = ABIType{ABIType::Failure, 0};
221+
abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0};
222222
return make_tuple(bytes{}, abiType, rawString);
223223
}
224224
}

test/libsolidity/util/TestFileParser.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,22 @@ namespace soltest
9898
*/
9999
struct ABIType
100100
{
101-
enum Type {
101+
enum Type
102+
{
102103
UnsignedDec,
103104
SignedDec,
104105
Failure,
105106
None
106107
};
108+
109+
enum Align
110+
{
111+
AlignLeft,
112+
AlignRight
113+
};
114+
107115
Type type = ABIType::None;
116+
Align align = Align::AlignRight;
108117
size_t size = 0;
109118
};
110119

0 commit comments

Comments
 (0)