-
Notifications
You must be signed in to change notification settings - Fork 197
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
Approval testing for the Analyzer #387
Conversation
8b591f7
to
2be1191
Compare
Codecov Report
@@ Coverage Diff @@
## master #387 +/- ##
==========================================
+ Coverage 86.30% 86.45% +0.14%
==========================================
Files 67 67
Lines 4032 4075 +43
==========================================
+ Hits 3480 3523 +43
Misses 552 552
Continue to review full report at Codecov.
|
2827ae2
to
6050914
Compare
f90e902
to
525aa09
Compare
525aa09
to
c3b1f31
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.
Looks good, left a question to double check I'm not misunderstanding what this does 😅
case::empty("features/empty.fe"), | ||
case::events("features/events.fe"), | ||
case::external_contract("features/external_contract.fe"), | ||
case::for_loop_with_break("features/for_loop_with_break.fe"), |
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.
Just to double check: We now test the state of the context for all these fixtures as an additional category of tests that we run. These tests do not actually test the return values of the called functions which we continue to do as before here. Is that right?
fe/compiler/tests/cases/features.rs
Lines 112 to 237 in c3b1f31
#[rstest(fixture_file, input, expected, | |
case("for_loop_with_static_array.fe", &[], uint_token(30)), | |
case("for_loop_with_break.fe", &[], uint_token(15)), | |
case("for_loop_with_continue.fe", &[], uint_token(17)), | |
case("while_loop_with_continue.fe", &[], uint_token(1)), | |
case("while_loop.fe", &[], uint_token(3)), | |
case("while_loop_with_break.fe", &[], uint_token(1)), | |
case("while_loop_with_break_2.fe", &[], uint_token(1)), | |
case("if_statement.fe", &[uint_token(6)], uint_token(1)), | |
case("if_statement.fe", &[uint_token(4)], uint_token(0)), | |
case("if_statement_2.fe", &[uint_token(6)], uint_token(1)), | |
case("if_statement_with_block_declaration.fe", &[], uint_token(1)), | |
case("ternary_expression.fe", &[uint_token(6)], uint_token(1)), | |
case("ternary_expression.fe", &[uint_token(4)], uint_token(0)), | |
case("call_statement_without_args.fe", &[], uint_token(100)), | |
case("call_statement_with_args.fe", &[], uint_token(100)), | |
case("call_statement_with_args_2.fe", &[], uint_token(100)), | |
case("return_bool_true.fe", &[], bool_token(true)), | |
case("return_bool_false.fe", &[], bool_token(false)), | |
case("return_bool_inverted.fe", &[bool_token(true)], bool_token(false)), | |
case("return_bool_inverted.fe", &[bool_token(false)], bool_token(true)), | |
case("return_u256_from_called_fn_with_args.fe", &[], uint_token(200)), | |
case("return_u256_from_called_fn.fe", &[], uint_token(42)), | |
case("return_u256.fe", &[], uint_token(42)), | |
case("return_i256.fe", &[], int_token(-3)), | |
case("return_identity_u256.fe", &[uint_token(42)], uint_token(42)), | |
case("return_identity_u128.fe", &[uint_token(42)], uint_token(42)), | |
case("return_identity_u64.fe", &[uint_token(42)], uint_token(42)), | |
case("return_identity_u32.fe", &[uint_token(42)], uint_token(42)), | |
case("return_identity_u16.fe", &[uint_token(42)], uint_token(42)), | |
case("return_identity_u8.fe", &[uint_token(42)], uint_token(42)), | |
case("return_u128_cast.fe", &[], uint_token(42)), | |
case("return_i128_cast.fe", &[], int_token(-3)), | |
case("return_msg_sig.fe", &[], bytes32_token("febb0f7e")), | |
// binary operators | |
case("return_addition_u256.fe", &[uint_token(42), uint_token(42)], uint_token(84)), | |
case("return_addition_i256.fe", &[int_token(-42), int_token(-42)], int_token(-84)), | |
case("return_addition_i256.fe", &[int_token(-42), int_token(42)], int_token(0)), | |
case("return_addition_u128.fe", &[uint_token(42), uint_token(42)], uint_token(84)), | |
case("return_subtraction_u256.fe", &[uint_token(42), uint_token(42)], uint_token(0)), | |
case("return_subtraction_i256.fe", &[int_token(-42), int_token(-42)], int_token(0)), | |
case("return_subtraction_i256.fe", &[int_token(-42), int_token(42)], int_token(-84)), | |
case("return_multiplication_u256.fe", &[uint_token(42), uint_token(42)], uint_token(1764)), | |
case("return_multiplication_i256.fe", &[int_token(-42), int_token(-42)], int_token(1764)), | |
case("return_multiplication_i256.fe", &[int_token(-42), int_token(42)], int_token(-1764)), | |
case("return_division_u256.fe", &[uint_token(42), uint_token(42)], uint_token(1)), | |
case("return_division_i256.fe", &[int_token(-42), int_token(-42)], int_token(1)), | |
case("return_division_i256.fe", &[int_token(-1), int_token(1)], int_token(-1)), | |
case("return_division_i256.fe", &[int_token(-42), int_token(42)], int_token(-1)), | |
case("return_pow_u256.fe", &[uint_token(2), uint_token(0)], uint_token(1)), | |
case("return_pow_u256.fe", &[uint_token(2), uint_token(4)], uint_token(16)), | |
case("return_pow_i256.fe", &[int_token(-2), uint_token(3)], int_token(-8)), | |
case("return_mod_u256.fe", &[uint_token(5), uint_token(2)], uint_token(1)), | |
case("return_mod_u256.fe", &[uint_token(5), uint_token(3)], uint_token(2)), | |
case("return_mod_u256.fe", &[uint_token(5), uint_token(5)], uint_token(0)), | |
case("return_mod_i256.fe", &[int_token(5), int_token(2)], int_token(1)), | |
case("return_mod_i256.fe", &[int_token(5), int_token(3)], int_token(2)), | |
case("return_mod_i256.fe", &[int_token(5), int_token(5)], int_token(0)), | |
case("return_bitwiseand_u256.fe", &[uint_token(12), uint_token(25)], uint_token(8)), | |
case("return_bitwiseand_u128.fe", &[uint_token(12), uint_token(25)], uint_token(8)), | |
case("return_bitwiseor_u256.fe", &[uint_token(12), uint_token(25)], uint_token(29)), | |
case("return_bitwisexor_u256.fe", &[uint_token(12), uint_token(25)], uint_token(21)), | |
case("return_bitwiseshl_u256.fe", &[uint_token(212), uint_token(0)], uint_token(212)), | |
case("return_bitwiseshl_u256.fe", &[uint_token(212), uint_token(1)], uint_token(424)), | |
case("return_bitwiseshr_u256.fe", &[uint_token(212), uint_token(0)], uint_token(212)), | |
case("return_bitwiseshr_u256.fe", &[uint_token(212), uint_token(1)], uint_token(106)), | |
case("return_bitwiseshr_i256.fe", &[int_token(212), uint_token(0)], int_token(212)), | |
case("return_bitwiseshr_i256.fe", &[int_token(212), uint_token(1)], int_token(106)), | |
// comparison operators | |
case("return_eq_u256.fe", &[uint_token(1), uint_token(1)], bool_token(true)), | |
case("return_eq_u256.fe", &[uint_token(1), uint_token(2)], bool_token(false)), | |
case("return_noteq_u256.fe", &[uint_token(1), uint_token(1)], bool_token(false)), | |
case("return_noteq_u256.fe", &[uint_token(1), uint_token(2)], bool_token(true)), | |
case("return_lt_u256.fe", &[uint_token(1), uint_token(2)], bool_token(true)), | |
case("return_lt_u256.fe", &[uint_token(1), uint_token(1)], bool_token(false)), | |
case("return_lt_u256.fe", &[uint_token(2), uint_token(1)], bool_token(false)), | |
case("return_lt_u128.fe", &[uint_token(1), uint_token(2)], bool_token(true)), | |
// lt_i256 with positive and negative numbers | |
case("return_lt_i256.fe", &[int_token(1), int_token(2)], bool_token(true)), | |
case("return_lt_i256.fe", &[int_token(1), int_token(1)], bool_token(false)), | |
case("return_lt_i256.fe", &[int_token(2), int_token(1)], bool_token(false)), | |
case("return_lt_i256.fe", &[int_token(-2), int_token(-1)], bool_token(true)), | |
case("return_lt_i256.fe", &[int_token(-1), int_token(-1)], bool_token(false)), | |
case("return_lt_i256.fe", &[int_token(-1), int_token(-2)], bool_token(false)), | |
case("return_lte_u256.fe", &[uint_token(1), uint_token(2)], bool_token(true)), | |
case("return_lte_u256.fe", &[uint_token(1), uint_token(1)], bool_token(true)), | |
// lte_i256 with positive and negative numbers | |
case("return_lte_u256.fe", &[uint_token(2), uint_token(1)], bool_token(false)), | |
case("return_lte_i256.fe", &[int_token(1), int_token(2)], bool_token(true)), | |
case("return_lte_i256.fe", &[int_token(1), int_token(1)], bool_token(true)), | |
case("return_lte_i256.fe", &[int_token(2), int_token(1)], bool_token(false)), | |
case("return_lte_i256.fe", &[int_token(-2), int_token(-1)], bool_token(true)), | |
case("return_lte_i256.fe", &[int_token(-1), int_token(-1)], bool_token(true)), | |
case("return_lte_i256.fe", &[int_token(-1), int_token(-2)], bool_token(false)), | |
case("return_gt_u256.fe", &[uint_token(2), uint_token(1)], bool_token(true)), | |
case("return_gt_u256.fe", &[uint_token(1), uint_token(1)], bool_token(false)), | |
case("return_gt_u256.fe", &[uint_token(1), uint_token(2)], bool_token(false)), | |
// gt_i256 with positive and negative numbers | |
case("return_gt_i256.fe", &[int_token(2), int_token(1)], bool_token(true)), | |
case("return_gt_i256.fe", &[int_token(1), int_token(1)], bool_token(false)), | |
case("return_gt_i256.fe", &[int_token(1), int_token(2)], bool_token(false)), | |
case("return_gt_i256.fe", &[int_token(-1), int_token(-2)], bool_token(true)), | |
case("return_gt_i256.fe", &[int_token(-1), int_token(-1)], bool_token(false)), | |
case("return_gt_i256.fe", &[int_token(-2), int_token(-1)], bool_token(false)), | |
case("return_gte_u256.fe", &[uint_token(2), uint_token(1)], bool_token(true)), | |
case("return_gte_u256.fe", &[uint_token(1), uint_token(1)], bool_token(true)), | |
case("return_gte_u256.fe", &[uint_token(1), uint_token(2)], bool_token(false)), | |
// gte_i256 with positive and negative numbers | |
case("return_gte_i256.fe", &[int_token(2), int_token(1)], bool_token(true)), | |
case("return_gte_i256.fe", &[int_token(1), int_token(1)], bool_token(true)), | |
case("return_gte_i256.fe", &[int_token(1), int_token(2)], bool_token(false)), | |
case("return_gte_i256.fe", &[int_token(-1), int_token(-2)], bool_token(true)), | |
case("return_gte_i256.fe", &[int_token(-1), int_token(-1)], bool_token(true)), | |
case("return_gte_i256.fe", &[int_token(-2), int_token(-1)], bool_token(false)), | |
// `and` bool operation | |
case("return_bool_op_and.fe", &[bool_token(true), bool_token(true)], bool_token(true)), | |
case("return_bool_op_and.fe", &[bool_token(true), bool_token(false)], bool_token(false)), | |
case("return_bool_op_and.fe", &[bool_token(false), bool_token(true)], bool_token(false)), | |
case("return_bool_op_and.fe", &[bool_token(false), bool_token(false)], bool_token(false)), | |
// `or` bool operation | |
case("return_bool_op_or.fe", &[bool_token(true), bool_token(true)], bool_token(true)), | |
case("return_bool_op_or.fe", &[bool_token(true), bool_token(false)], bool_token(true)), | |
case("return_bool_op_or.fe", &[bool_token(false), bool_token(true)], bool_token(true)), | |
case("return_bool_op_or.fe", &[bool_token(false), bool_token(false)], bool_token(false)), | |
)] | |
fn test_method_return(fixture_file: &str, input: &[ethabi::Token], expected: ethabi::Token) { |
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, we are just testing the state of the context. Anytime we change something in the analyzer that results in a different context output for a given fixture, it will show up here.
There have been a number of times where I've been reworking things in the analyzer and ended up breaking some unrelated full-compilation fixture test. Resolving these types of issues is tedious, since it's not clear what changed in the analyzer output. With this, it will be obvious what changed.
What was wrong?
Testing around the Analyzer was not very thorough.
How was it fixed?
We now generate snapshots of
Context
using insta. The snapshots are formatted using codespan and the debug implementation of attributes. Here are a few things to note:As an example, this is what would show up during insta review if you changed the location of numeric literals from
value
tomemory
:Notice that the same node is displayed twice. This is because the list of nodes used to generate the output is built by pushing nodes passed into
context.add_
methods. These add methods are called twice in some situations, so we end up with duplicates. I think this should be fixed by adding update methods toContext
, so we're not calling adds multiple times. TODO: write an issue for thisTo-Do