Skip to content

[TO BE REDONE] Infrastructure for extracting semantics tests.#4245

Closed
ekpyron wants to merge 7 commits intodevelopfrom
semanticsTests
Closed

[TO BE REDONE] Infrastructure for extracting semantics tests.#4245
ekpyron wants to merge 7 commits intodevelopfrom
semanticsTests

Conversation

@ekpyron
Copy link
Copy Markdown
Collaborator

@ekpyron ekpyron commented Jun 7, 2018

Closes #4223.

Encoding and decoding of arguments and results is still a mess, although it should already be functional for many cases.

@ekpyron ekpyron self-assigned this Jun 7, 2018
@ekpyron ekpyron force-pushed the semanticsTests branch 6 times, most recently from 875f75b to dacf1da Compare June 7, 2018 13:02
{ return std::unique_ptr<TestCase>(new SyntaxTest(_filename)); }
SyntaxTest(std::string const& _filename);

bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please always use override for virtual functions, and perhaps even virtual in the derived class.

namespace test
{

class TestCase
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please mention that this is the common superclass of syntax and semantics tests

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also please document the virtual functions.

class TestCase
{
public:
typedef std::unique_ptr<TestCase>(*TestCaseCreator)(std::string const&);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use using x = y instead of typedef.

@ekpyron ekpyron force-pushed the semanticsTests branch 10 times, most recently from dd03447 to 1387318 Compare June 8, 2018 12:25
@ekpyron ekpyron changed the title [WIP] Infrastructure for extracting semantics tests. Infrastructure for extracting semantics tests. Jun 8, 2018
string public s;
function set(string _s) external returns (bool) {
s = _s;
return true;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now returns a bool, since "no return data" will be considered the same as "revert" - so far I haven't found a reliable way to distinguish between the two using the cpp-ethereum JSON RPC interface.

@ekpyron
Copy link
Copy Markdown
Collaborator Author

ekpyron commented Jun 8, 2018

Still missing (among others):

  • DEPLOY command, resp. supplying arguments and sending ether to constructors.
  • instantiating libraries

Edit: DEPLOY and libraries are added now.

@ekpyron ekpyron force-pushed the semanticsTests branch 3 times, most recently from 69fa34d to d82d990 Compare June 8, 2018 13:53
// ----
// f(bool): true
// -> 1
// f(bool): false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

f(bool,uint)->(uint,uint)
true|2->2|3

Copy link
Copy Markdown
Contributor

@axic axic Jun 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To explain: first parentheses contains the argument types, comma separated, while the second one contains the return parameters, comma separated.

The expectations follow the same pattern, but instead of comma are separated by the pipe symbol, in case the comma could be a valid token in inputs. But I think comma should be fine, since we only support dot for number literals.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, now I get it. I think adding parentheses in the second line might help reading this:

f(bool,uint)->(uint,uint)
(true|2)->(2|3)

And maybe using commas instead of pipes in the second line might be fine as well (I'm not sure commas will need to be a valid input token outside of strings and within strings pipes may occur as well...).

This syntax has the advantage of making the desired encoding of the return values explicit (at the moment I'm trying to deduce the types from an untyped-list and try to re-encode the actual results using those deduced types, but that's probably more error-prone).

However, using typed return values will make it more difficult to support supplying unaligned/weird inputs - although we might just use special return types for that (like "unpaddedbytes" that can be encoded e.g. as a hex string).

@chriseth What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about f(bool,uint)->raw for the special case?

e.g.

f(bool,uint)->raw
(true,false)->0011442200440..00

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I had in mind, yes - but now I realize: that still won't allow you to provide malformed, resp. strangely encoded inputs... and we can't change the left hand side of the first line to f(raw), since we need the correct signature for the call.

That's related to @chriseth's comment in the issue, i.e. the idea was not force you to use correctly ABI-encoded results as well as inputs in order to be able to check the behavior if a function is supplied with malformed input.

That's why currently the input encoding is completely independent of the function signature and no return signature is provided at all.

We could allow something like:

f(bool,uint)->raw
raw:112233445566...FF->00114422004400..00

But I'm not sure that's better than the current solution of generally using an untyped encoding both for input and return values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this then (also whitespaces should be allowed below):

f(bool,uint)->(uint,uint)
true,1->1,2
f(bool,uint)->(uint,uint)
raw:00aa112200->raw:00110044

If the section starts with raw: then it is considered raw, independent from the types declared.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will make it difficult for isoltest to realize that it should re-encode mismatching actual results as raw bytes again and not to use two uint's instead, so I think

f(bool,uint)->raw
raw:001122...->raw:001122

would probably be better. The actual return signature of the function is not parsed anyways, so specifying it in the test expectations won't have an effect apart from guiding parsing and re-encoding of return values.

Furthermore, actually using the signatures plus the raw construction won't allow it to mix regularly encoded and raw bytes, but that's probably not needed anyways.

In general the first thing we need to agree on is whether we want to use the function signature at all for encoding the input - if we agree on that, I could already start changing the PR accordingly.

As a reminder: so far this PR ignores the function signature entirely and input arguments are specified by a comma separated list of values whose type is automatically deduced and padded to 32-bytes by default, but padding can be disabled using unpadded, so:

f(bool,uint): true, 1234
-> 0x11, 0x22

currently will encode the input as two 32-bytes blocks and expect two 32-bytes blocks as output, and

f(bool,uint): unpadded(hex"00000000000000000000000000000000", 1), 1234
-> 0x11, 0x22

will be the same (the hex string is 31 bytes and the single 1 will be the 32nd byte, which together is the standard 32-bytes encoding of the bool true).

So shall we discard this and instead use the function signature to guide the encoding by default? @chriseth What do you think?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@axic Another issue to think about is struct's - we could support them in the signature as well and have nested parentheses when specifying arguments, but it will complicate things further and it will be easier to deal with them using the current "untyped" solution.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the ability to specify incorrectly encoded input and output should not have a high priority.
Still, the current solutions are not exactly what I would call readable. Why do we have to specify the types at all? If we go down that route, we might consider an earlier suggestion and use

f(true, 7) == 7, 8

where isoltest just asks the compiler for the types. The case of multiple functions with the same name might also be an edge case that can be solved with raw encoding.

Structs could be out of scope for now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. The current solution is the so far closest to the current tests in SolidityEndToEndTest.cpp.

The main question is probably whether we want to let the encoding of arguments and return values actually depend on the function (and return) signature at all or not. That would mean to use some kind of ABI encode/decode and the tests would depend on those to be correct. If one goes down that road, I wonder why one wouldn't just move the check into the contract instead, i.e.:

contract C {
    function f(bool a, int b) returns (uint, uint) { ... }
    function test() returns (bool) { return f(true, 7) == (7, 8); }
}

And then just verify whether test returns true (well, something like that - there's currently no tuple comparisons and one would need to care about internal and external calls, etc., but I think you get the idea).

@ekpyron ekpyron force-pushed the semanticsTests branch 2 times, most recently from e28deba to 1f4be2a Compare June 13, 2018 10:25
@ekpyron
Copy link
Copy Markdown
Collaborator Author

ekpyron commented Jun 15, 2018

The currently last two commits depend on (and include) #4305 and will make the tests fail until cpp-ethereum is updated.


Compiler Features:
* Type Checker: Show named argument in case of error.
* Tests: Determine transaction status during IPC calls.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case anybody wonders: this is only in here as part of #4305, on which this PR depends and which is not yet merged.

@ekpyron ekpyron force-pushed the semanticsTests branch 2 times, most recently from 921e079 to 3f481df Compare June 15, 2018 12:58
@ekpyron
Copy link
Copy Markdown
Collaborator Author

ekpyron commented Jun 15, 2018

Note: so far there is no way to extract tests for which the expectation is that contract deployment fails.

@ekpyron ekpyron force-pushed the semanticsTests branch 2 times, most recently from ff64013 to ade03c1 Compare June 19, 2018 15:05
@ekpyron ekpyron force-pushed the semanticsTests branch 2 times, most recently from 3a6287b to bc935b5 Compare July 2, 2018 12:11
@ekpyron ekpyron changed the title Infrastructure for extracting semantics tests. [TO BE REDONE] Infrastructure for extracting semantics tests. Nov 21, 2018
@ekpyron
Copy link
Copy Markdown
Collaborator Author

ekpyron commented Nov 21, 2018

To be clear about the state of this PR I added [TO BE REDONE] to the title. I'd keep the code for now, but this PR was hacky and meant to be a half-way solution to extract the tests fast - it should be redone "properly" now.

@erak
Copy link
Copy Markdown
Collaborator

erak commented Dec 13, 2018

Closing this because it's being redone by me on a different branch. I will open a PR soon.

@erak erak closed this Dec 13, 2018
@erak erak mentioned this pull request Jan 4, 2019
3 tasks
@ekpyron ekpyron deleted the semanticsTests branch May 8, 2019 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants