Skip to content

Commit 1b4311d

Browse files
test: add modifier ordering rule unit tests
1 parent dbc70bb commit 1b4311d

2 files changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# @version 0.4.2
2+
3+
# Correct ordering examples
4+
5+
@external
6+
@view
7+
def correct_external_view() -> uint256:
8+
return 42
9+
10+
@internal
11+
@pure
12+
def correct_internal_pure() -> uint256:
13+
return 123
14+
15+
@external
16+
@payable
17+
def correct_external_payable():
18+
pass
19+
20+
@external
21+
@nonreentrant
22+
def correct_external_nonreentrant():
23+
pass
24+
25+
@external
26+
@view
27+
@nonreentrant
28+
def correct_external_view_nonreentrant() -> uint256:
29+
return 42
30+
31+
@external
32+
@payable
33+
@nonreentrant
34+
def correct_external_payable_nonreentrant():
35+
pass
36+
37+
# Incorrect ordering examples
38+
39+
@view
40+
@external
41+
def incorrect_view_external() -> uint256:
42+
return 42
43+
44+
@pure
45+
@internal
46+
def incorrect_pure_internal() -> uint256:
47+
return 123
48+
49+
@nonreentrant
50+
@external
51+
def incorrect_nonreentrant_external():
52+
pass
53+
54+
@nonreentrant
55+
@view
56+
@external
57+
def incorrect_nonreentrant_view_external() -> uint256:
58+
return 42
59+
60+
@payable
61+
@nonreentrant
62+
@external
63+
def incorrect_payable_nonreentrant_external():
64+
pass
65+
66+
# Edge cases
67+
68+
@deploy
69+
def __init__():
70+
pass
71+
72+
@external
73+
def no_other_modifiers():
74+
pass
75+
76+
@internal
77+
def internal_only():
78+
pass
79+
80+
# Functions without explicit visibility (defaults to internal)
81+
82+
@pure
83+
def implicit_internal_pure() -> uint256:
84+
return 42
85+
86+
@view
87+
def implicit_internal_view() -> uint256:
88+
return 42
89+
90+
@nonreentrant
91+
def implicit_internal_nonreentrant():
92+
pass
93+
94+
# Incorrect ordering with implicit internal
95+
96+
@nonreentrant
97+
@view
98+
def incorrect_implicit_internal_nonreentrant_view() -> uint256:
99+
return 42
100+
101+
# Mixed correct and incorrect orderings
102+
@view
103+
def implicit_internal_view_correct() -> uint256:
104+
return 42
105+
106+
@nonpayable
107+
def implicit_internal_nonpayable_correct():
108+
pass
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import pytest
2+
from natrix import parse_file
3+
from natrix.rules.modifiers_ordering import ModifiersOrderingRule
4+
5+
6+
@pytest.fixture()
7+
def test_modifiers_ordering_contract():
8+
return parse_file("tests/contracts/test_modifiers_ordering.vy")
9+
10+
11+
def test_modifiers_ordering(test_modifiers_ordering_contract):
12+
rule = ModifiersOrderingRule()
13+
14+
issues = rule.run(test_modifiers_ordering_contract)
15+
16+
# We expect 6 issues for the incorrect ordering examples
17+
assert len(issues) == 6
18+
19+
# Check that we found all the incorrect orderings
20+
issue_messages = [issue.message for issue in issues]
21+
22+
# Check specific issues
23+
incorrect_functions = [
24+
"incorrect_view_external",
25+
"incorrect_pure_internal",
26+
"incorrect_nonreentrant_external",
27+
"incorrect_nonreentrant_view_external",
28+
"incorrect_payable_nonreentrant_external",
29+
"incorrect_implicit_internal_nonreentrant_view",
30+
]
31+
32+
for func_name in incorrect_functions:
33+
assert any(
34+
func_name in msg for msg in issue_messages
35+
), f"Expected issue for {func_name}"
36+
37+
# Verify the issue details for one specific case
38+
view_external_issue = next(
39+
(issue for issue in issues if "incorrect_view_external" in issue.message), None
40+
)
41+
assert view_external_issue is not None
42+
assert view_external_issue.code == "NTX12"
43+
assert view_external_issue.severity == "style"
44+
assert "@view, @external" in view_external_issue.message
45+
46+
# Verify implicit internal cases
47+
implicit_issue = next(
48+
(
49+
issue
50+
for issue in issues
51+
if "incorrect_implicit_internal_nonreentrant_view" in issue.message
52+
),
53+
None,
54+
)
55+
assert implicit_issue is not None
56+
assert "@nonreentrant, @view" in implicit_issue.message

0 commit comments

Comments
 (0)