-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Interactive syntax test tool. #3709
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
2a0d558
to
b7b493e
Compare
06ee88b
to
90975d3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I need another run through this to understand everything :)
test/libsolidity/FormattedPrinter.h
Outdated
Scope(std::ostream& _stream, bool const _enabled): m_stream(_stream), m_enabled(_enabled) {} | ||
~Scope() { try { if (m_enabled) m_stream << RESET; } catch(...) {} } | ||
template<typename T> | ||
std::ostream& operator<<(T&& t) { return m_stream << std::forward<T>(t); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_t
test/libsolidity/FormattedPrinter.h
Outdated
void enableFormatting() { m_enabled = true; } | ||
void disableFormatting() { m_enabled = false; } | ||
|
||
class Scope |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add a short ///
-comment that explains the purpose of this class.
test/libsolidity/FormattedPrinter.h
Outdated
std::ostream& m_stream; | ||
bool const m_enabled = false; | ||
}; | ||
Scope format(std::ostream& _stream, std::vector<const char*> const& _formatting) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
char const*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment about how to use this function would also be in order.
test/libsolidity/SyntaxTest.cpp
Outdated
else | ||
for (auto const& expectation: m_expectations) | ||
_stream << _indent << expectation.type << ": " << expectation.message << endl; | ||
format(_stream, {expectation.type == "Warning" ? YELLOW : RED}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly, you would have to put each element between two shift operators on their own line. This will probably look weird, but please at least put the first <<
at the end of the first line.
} | ||
|
||
void SyntaxTest::printErrorList( | ||
ostream& _stream, | ||
ErrorList const& _errorList, | ||
string const& _indent | ||
string const& _linePrefix, | ||
bool const _ignoreWarnings, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use enums instead? I'm fine with named bit fields, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure it makes sense to define an enum/bit field for this single function alone?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, because then you know what the bools mean.
test/tools/isoltest.cpp
Outdated
if (_parserError) | ||
cout << "(e)dit/(s)kip/(q)uit? "; | ||
else | ||
cout << "(e)dit/(r)eplace/(s)kip/(q)uit? "; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps (u)pdate expectations
instead of (r)eplace
?
test/tools/isoltest.cpp
Outdated
return true; | ||
case 'r': | ||
cout << endl; | ||
if (!_parserError) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens here in case of a parser error?
test/tools/isoltest.cpp
Outdated
if (!m_test->errorList().empty()) | ||
{ | ||
m_test->disableFormatting(); | ||
m_test->printErrorList(file, m_test->errorList(), "// ", false, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to add a _formatting
parameter to printErrorList
?
test/tools/isoltest.cpp
Outdated
m_test->enableFormatting(); | ||
} | ||
} | ||
return process(_successCount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add a message "Re-running test case..."
?
test/tools/isoltest.cpp
Outdated
|
||
|
||
bool SyntaxTestTool::processPath( | ||
fs::path const& _basepath, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it important to distinguish between _basepath
and _path
for this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say that the output of isoltest is more readable, if it prints paths relative to the base path and not absolute paths -
41ff4d4
to
cb59b7d
Compare
254a1d3
to
9936faf
Compare
@chriseth I think this should be ready for another review now. |
796aeaa
to
c64baa4
Compare
test/tools/isoltest.cpp
Outdated
} | ||
case 'e': | ||
cout << endl << endl; | ||
if (system((editor + " " + m_path.string()).c_str())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
system
is the only possibility I know of that is part of the C++11 standard.
execv
et al. would require a distinction between unix and windows.
boost::process
is only included in boost >= 1.64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should at least quote the path.
6948cbd
to
79c46d1
Compare
I noticed that non-bold cyan and yellow are not too well readable on my screen. Furthermore, perhaps we should not overdo it with the colours. For example, reading a full contract printed in colour is a little cumbersome. What about colouring the words |
{ | ||
success = m_test->run(outputMessages, " ", m_formatted); | ||
} | ||
catch (...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I asked that before, but under which circumstances can we have an exception here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah nevermind, I found it. Can you please add a comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, actually in the medium term, this tool should also be used for parser tests, in which case we need to use a different framework and thus would not get an exception here, but we can keep it like that for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes - in the medium term it would be best to use/write/modify a framework that gracefully returns both parser and syntax errors, instead of catching exceptions here.
I would still like to keep the colors for the results and expected results to distinguish optically between warnings and errors. I will change it to bold yellow and red and we can see whether that helps. The contract can be displayed in white, though, and instead the headings (Contract:, etc.) in maybe also bold cyan. |
{ | ||
cout << " "; | ||
FormattedScope(cout, m_formatted, {INVERSE, RED}) << "Parsing failed:" << endl; | ||
m_test->printErrorList(cout, m_test->compilerErrors(), " ", true, true, m_formatted); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are the warnings ignored here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case of a parser error the warnings don't really matter - it means the contract cannot be properly parsed due to some errors and the user is supposed to fix those errors by manually editing the contract - warnings would only be a distraction here.
This will, of course, change in future versions of the tool that includes parsing tests, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, we can keep it like that. The main reason I'm asking here is because if we do not need to ignore warning, we can get rid of one of the three bool parameters.
@ekpyron what about keeping the colours only for the error type and not the whole message? |
79c46d1
to
7fa892e
Compare
@chriseth That might be a good compromise. I first squashed bold colours and cyan for headings, white for the contract into the old commits and then added a new commit that only colours the error type, not the message. I actually preferred the old colour scheme, but I'm fine with this as well (the actual result will largely depend on the used terminal emulator). |
@chriseth I see only now that you approved the changes before the last commit (which changes the bool arguments for SyntaxTest::printErrorList to an enum). I actually prefer bool arguments in this particular case, since I don't think these arguments make up a meaningful enum (although in general, I agree that functions with lots of bool arguments should be avoided). Also the enum itself would be misplaced outside the SyntaxTest class or directly inside the SyntaxTest class as old-style enum, so I used an enum class as bitfield, which in turn means having to overload its operators... In any case I'm fine with merging with or without this last change. |
Sorry for the mis-communication. I agree that in this particular case, we are probably better off without the enum, especially since we can hopefully remove one or two of the bools in the medium term. For example, it might be useful to also include the line numbers into the expectations. |
a65b650
to
50ad89d
Compare
Refs #3644.
Adds an interactive test tool that runs all syntax tests and for failing tests allows to interactively edit the test or replace the test expectations with the actual test results.
Part of #3674.
Depends on #3707 and #3708.