Skip to content

Conversation

@federico-stacks
Copy link

@federico-stacks federico-stacks commented Oct 28, 2025

Description

This PR adds consensus test coverage for the ParseError enum in preparation for the upcoming refactor of that enum. The PR is currently a draft to gather early feedback on test organization and macro usage.

The PR is currently a draft to gather early feedback about test organization and macro usage::

  1. Although this is not to be intended as the final structure, I’ve started isolating ParseError related tests in a dedicate module parse_tests.rs
  2. To support this, I've exported the contract_deploy_consensus_test! and contract_call_consensus_test! macros opting for:
    • scoped export, to prevent visibilitty at the crate root level
    • impoort consistency, so macros can be used without additional imports (i.e., resolving internal macro dependencies using absolute namespaces).
  3. Futhermore I've added clarity_types crate as test dependency for documentation purposes (doc referencing Parse error variants). This is just a preliminary attempt, and I open to remove it if it's not beneficial (I'm also trying understanding this)
    • Currently, it doesn’t work properly with the macro, causing IDE warnings and broken hyperlinks (would function correctly with a standard test function)

    • I also noticed that with the macro we loose the Outline view (is empty)

      So, apart the doc thing, I'm wondering if in general would be convenient having "native" test functions while keeping the macro just for configuring the test body. Something like this:

    #[test]
    fn test_parse_error_lexer() {
        contract_deploy_consensus_test!(
           parse_error__import_trait_bad_signature,
           contract_name: "my-contract",
           contract_code: &{"(use-trait)"},
       );
    }

Applicable issues

Additional info (benefits, drawbacks, caveats)

Checklist

  • Test coverage for new or modified code paths
  • Changelog is updated
  • Required documentation changes (e.g., docs/rpc/openapi.yaml and rpc-endpoints.md for v2 endpoints, event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo

@federico-stacks federico-stacks self-assigned this Oct 28, 2025
@federico-stacks federico-stacks added aac Avoiding Accidental Consensus aac-testing Avoiding Accidental Consensus Testing Specific Task labels Oct 28, 2025
@federico-stacks federico-stacks linked an issue Oct 28, 2025 that may be closed by this pull request

/// ParserError: [`ParseErrors::Lexer`]
/// Caused by: unknown symbol
/// Outcome: block accepted.

Choose a reason for hiding this comment

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

I like your comments. Clear, concise, easy to follow/reason about.

@jacinta-stacks
Copy link

I actually think it might be slightly easier to reason about the test name/be able to find tests if we did something like

#[test]
fn test_parse_error_lexer() {
    contract_deploy_consensus_test!(
       function_name!(),
       contract_name: "my-contract",
       contract_code: &{"(use-trait)"},
   );
}

since when I initially looked at contract_deploy_consensus_test! macro it took me a bit to realize it was a #[test]. But I am not strongly one way or the other. Whichever makes it easier for you to reuse these functions in your test, go for it. If you need help fixing your errors, let me know. I will give it a look.

@federico-stacks
Copy link
Author

I actually think it might be slightly easier to reason about the test name/be able to find tests if we did something like

#[test]
fn test_parse_error_lexer() {
    contract_deploy_consensus_test!(
       function_name!(),
       contract_name: "my-contract",
       contract_code: &{"(use-trait)"},
   );
}

since when I initially looked at contract_deploy_consensus_test! macro it took me a bit to realize it was a #[test]. But I am not strongly one way or the other. Whichever makes it easier for you to reuse these functions in your test, go for it. If you need help fixing your errors, let me know. I will give it a look.

Considering we have a macro, we should be able to use function_name!() internally.
Otherwise, if we also expose the function_name() as in your example, we could even replace the macro with a function.

@federico-stacks
Copy link
Author

Based on the feedback, I've updated consensus macros as proposed in the PR description.
It seems to work nicely (with documentation, but also I added a should_panic test for unreachable error variant)

By the way, adding more tests exposed a new issue related to the vm_error field, basically this test:

#[test]
fn test_circular_reference() {
    contract_deploy_consensus_test!(
        contract_name: "my-contract",
        contract_code: &{"
            (define-constant my-a my-b)
            (define-constant my-b my-a)
        "},
    );
}

produce a non-deterministic vm_error description. Here the possible output:

  • detected interdependent functions (my-a, my-b)
  • detected interdependent functions (my-b, my-a)

where the element listed in the paranthesis can have a different order and the flip/flop between them at each run.

@codecov
Copy link

codecov bot commented Oct 30, 2025

Codecov Report

❌ Patch coverage is 87.39496% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.38%. Comparing base (f8d02cd) to head (298959a).

Files with missing lines Patch % Lines
stackslib/src/chainstate/tests/parse_tests.rs 85.98% 15 Missing ⚠️

❌ Your project check has failed because the head coverage (74.38%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #6631      +/-   ##
===========================================
+ Coverage    64.85%   74.38%   +9.52%     
===========================================
  Files          574      575       +1     
  Lines       355039   355145     +106     
===========================================
+ Hits        230278   264188   +33910     
+ Misses      124761    90957   -33804     
Files with missing lines Coverage Δ
stackslib/src/chainstate/tests/consensus.rs 95.00% <100.00%> (+9.78%) ⬆️
stackslib/src/chainstate/tests/mod.rs 70.08% <ø> (ø)
stackslib/src/chainstate/tests/parse_tests.rs 85.98% <85.98%> (ø)

... and 373 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f8d02cd...298959a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@francesco-stacks francesco-stacks left a comment

Choose a reason for hiding this comment

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

Good changes! Definitely fine with the named tests.

PS:I am sure you already noticed, but some unit tests are currently failing

use clarity::vm::ast::stack_depth_checker::AST_CALL_STACK_DEPTH_BUFFER;
use clarity::vm::MAX_CALL_STACK_DEPTH;
#[allow(unused_imports)] // Just used for documentation purpose
use clarity_types::{errors::ParseErrors, ContractName};

Choose a reason for hiding this comment

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

nit: maybe we can directly import it from use clarity::vm::ast::errors::ParseErrors and avoid adding clarity_types directly?

Copy link
Author

Choose a reason for hiding this comment

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

you're right! the IDE didn't show auto-completition option to gather these symbols from clarity crate. Damn it :)

crc: 2ac068b

transactions: [
ExpectedTransactionOutput(
tx: "SmartContract(name: my-contract-Epoch3_3-Clarity4, code_body: [..], clarity_version: Some(Clarity4))",
vm_error: "Some(use of undeclared trait <my-trait>) [NON-CONSENSUS BREAKING]",

Choose a reason for hiding this comment

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

damn, that's a pity that vm_error contains the "message" of the error and not the error variant itself

Comment on lines 48 to 50
contract_code: &{"
(define-data-var my-int int 340282366920938463463374607431768211455)
"},

Choose a reason for hiding this comment

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

nit, you can remove &{ in case you pass a string slice

Suggested change
contract_code: &{"
(define-data-var my-int int 340282366920938463463374607431768211455)
"},
contract_code: "(define-data-var my-int int 340282366920938463463374607431768211455)",

even multiline strings will work fine

Copy link
Author

Choose a reason for hiding this comment

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

crc: 730fc6d

@federico-stacks
Copy link
Author

Good changes! Definitely fine with the named tests.

PS:I am sure you already noticed, but some unit tests are currently failing

Yeah! This is due the vm_error for the test_circular_reference being not deterministic as mentioned in this comment: #6631 (comment)

@federico-stacks federico-stacks force-pushed the chore/aac-parse-error-test branch from 27b1d56 to a81db5d Compare October 31, 2025 12:10
@federico-stacks
Copy link
Author

By the way, adding more tests exposed a new issue related to the vm_error field, basically this test:

#[test]
fn test_circular_reference() {
    contract_deploy_consensus_test!(
        contract_name: "my-contract",
        contract_code: &{"
            (define-constant my-a my-b)
            (define-constant my-b my-a)
        "},
    );
}

produce a non-deterministic vm_error description. Here the possible output:

  • detected interdependent functions (my-a, my-b)
  • detected interdependent functions (my-b, my-a)

where the element listed in the paranthesis can have a different order and the flip/flop between them at each run.

I opted to manage this issue, forcing the CircularRefercence being emitted with a determinitic list.
see commit: a81db5d

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aac Avoiding Accidental Consensus aac-testing Avoiding Accidental Consensus Testing Specific Task

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AAC Testing: Add test coverage for ParseError enum

3 participants