Skip to content

test(mutator): add AST mutator validity test#15

Open
egyptianswitftpigeon wants to merge 9 commits intomainfrom
feat/mutator-test
Open

test(mutator): add AST mutator validity test#15
egyptianswitftpigeon wants to merge 9 commits intomainfrom
feat/mutator-test

Conversation

@egyptianswitftpigeon
Copy link
Copy Markdown
Collaborator

Summary

  • Add test that validates the AST mutator produces semantically valid Vyper code
  • Parameterized on vyper-exports corpus with deterministic seeds for reproducibility
  • Verifies mutations actually change the AST and compilation matches xfail expectations
  • Fix import path in stmt_generator.py (src.fuzzer -> fuzzer)

Test plan

  • Run ./ivytest.sh tests/mutator/test_ast_mutator.py to execute the new tests
  • Verify linting passes with ruff check and pyright

🤖 Generated with Claude Code

cyberthirst and others added 9 commits January 11, 2026 14:21
Bug #1: The reduced() method returns cached constant-folded values
from original semantic analysis, not the current mutated value. This
caused validation to check wrong values after mutations.

Fix: Use node.value directly to get the actual current value after
mutation. Add _check_subscript_index_validity() to validate indices
and add xfails for negative or out-of-bounds indices.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug #1 & #6: Add _check_subscript_context() to validate Int nodes
when used as subscript indices or type annotation sizes:

- Use node.value directly (not reduced()) to get current mutated value
- Detect type annotation context (Bytes[N], String[N], etc.)
- Add xfail for array/bytes sizes <= 0
- Add xfail for negative indices
- Add xfail for out-of-bounds static array access

Call validation after all int literal mutations (_add_one, _subtract_one,
_set_zero, _type_aware_mutate).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug #2: bytesM types (bytes1-bytes32) require 0x... syntax,
not x"..." syntax. Changed _bytesm_to_ast() to use ast.Hex
with 0x prefix instead of ast.HexBytes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug #3: Vyper's constant folding evaluates BOTH branches of ternary
expressions before checking the condition. A guard like
`0 if (len == 0) else x % len` still fails because Vyper evaluates
`x % len` even when len is 0.

Fix: Use `max(1, len)` as the divisor instead of ternary guards.
This ensures the divisor is always >= 1, preventing divide-by-zero
during constant folding.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug #4: Vyper does not support len() on static arrays (SArrayT).
The builtin only works on DynArray, Bytes, and String types.

Fix: In _guarded_index(), check if the sequence is SArrayT and use
seq_t.length (the compile-time known length) instead of generating
a len() call. Dynamic arrays still use len() for runtime length.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Vyper doesn't support tuple literals on the RHS of assignment
statements. This fix prevents generating such invalid code by:
- Skipping TupleT targets in generate_assign
- Returning False for TupleT in assign mutation is_applicable checks
- Excluding TupleT immutables from __init__ initialization

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
For SArrayT, generate indices in the valid range [0, length-1] instead
of arbitrary uint256 expressions. Since static array length is known at
compile time, we can avoid generating out-of-bounds indices that would
cause compilation failures.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add test that validates the mutator produces semantically valid Vyper code:
- Parameterized on vyper-exports corpus
- Uses deterministic seeds for reproducibility
- Verifies mutations actually change the AST
- Checks compilation matches xfail expectations

Also fix import path in stmt_generator.py (src.fuzzer -> fuzzer).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.

2 participants